Skip to content

Commit b4fb9aa

Browse files
authored
[clang] Fix of a crash 'Cannot get layout of forward declarations' during CTU static analysis (#155375)
When a type is imported with `ASTImporter`, the "original declaration" of the type is imported. In some cases this is not the definition (of the class). Before the fix the definition was only imported if there was an other reference to it in the AST to import. This is not always the case (like in the added test case), if not the definition was missing in the "To" AST which can cause the assertion later.
1 parent a805dfb commit b4fb9aa

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

clang/lib/AST/ASTImporter.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1740,10 +1740,21 @@ ExpectedType ASTNodeImporter::VisitDeducedTemplateSpecializationType(
17401740
}
17411741

17421742
ExpectedType ASTNodeImporter::VisitTagType(const TagType *T) {
1743-
Expected<TagDecl *> ToDeclOrErr = import(T->getOriginalDecl());
1743+
TagDecl *DeclForType = T->getOriginalDecl();
1744+
Expected<TagDecl *> ToDeclOrErr = import(DeclForType);
17441745
if (!ToDeclOrErr)
17451746
return ToDeclOrErr.takeError();
17461747

1748+
if (DeclForType->isUsed()) {
1749+
// If there is a definition of the 'OriginalDecl', it should be imported to
1750+
// have all information for the type in the "To" AST. (In some cases no
1751+
// other reference may exist to the definition decl and it would not be
1752+
// imported otherwise.)
1753+
Expected<TagDecl *> ToDefDeclOrErr = import(DeclForType->getDefinition());
1754+
if (!ToDefDeclOrErr)
1755+
return ToDefDeclOrErr.takeError();
1756+
}
1757+
17471758
if (T->isCanonicalUnqualified())
17481759
return Importer.getToContext().getCanonicalTagType(*ToDeclOrErr);
17491760

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
5+
// RUN: %clang_cc1 -emit-pch -o %t/import.c.ast %t/import.c
6+
7+
// RUN: %clang_extdef_map -- -x c %t/import.c >> %t/externalDefMap.txt
8+
// RUN: sed -i 's/$/.ast/' %t/externalDefMap.txt
9+
10+
// RUN: %clang_cc1 -analyze \
11+
// RUN: -analyzer-checker=core \
12+
// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \
13+
// RUN: -analyzer-config display-ctu-progress=true \
14+
// RUN: -analyzer-config ctu-dir=%t \
15+
// RUN: -verify %t/main.c
16+
17+
//--- main.c
18+
19+
// expected-no-diagnostics
20+
21+
typedef struct X_s X_t;
22+
unsigned long f_import(struct X_s *xPtr);
23+
24+
static void freeWriteFileResources(struct X_s *xPtr) {
25+
f_import(xPtr);
26+
}
27+
28+
//--- import.c
29+
30+
typedef struct Y_s Y_t;
31+
32+
struct Y_s {
33+
};
34+
35+
struct X_s {
36+
Y_t y;
37+
};
38+
39+
unsigned long f_import(struct X_s *xPtr) {
40+
if (xPtr != 0) {
41+
}
42+
return 0;
43+
}

0 commit comments

Comments
 (0)