[llvm-branch-commits] [clang] 68f5396 - [ASTImporter] Fix import of a typedef that has an attribute

2020-12-14 Thread Gabor Marton via llvm-branch-commits

Author: Gabor Marton
Date: 2020-12-14T18:27:05+01:00
New Revision: 68f53960e17d93c3a2727164dac4e54140bd98ba

URL: 
https://github.com/llvm/llvm-project/commit/68f53960e17d93c3a2727164dac4e54140bd98ba
DIFF: 
https://github.com/llvm/llvm-project/commit/68f53960e17d93c3a2727164dac4e54140bd98ba.diff

LOG: [ASTImporter] Fix import of a typedef that has an attribute

The import of a typedefs with an attribute uses clang::Decl::setAttrs().
But that needs the ASTContext which we can get only from the
TranslationUnitDecl. But we can get the TUDecl only thourgh the
DeclContext, which is not set by the time of the setAttrs call.

Fix: import the attributes only after the DC is surely imported.
Btw, having the attribute import initiated from GetImportedOrCreateDecl was
fundamentally flawed. Now that is implicitly fixed.

Differential Revision: https://reviews.llvm.org/D92962

Added: 


Modified: 
clang/lib/AST/ASTImporter.cpp
clang/unittests/AST/ASTImporterTest.cpp

Removed: 




diff  --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index ea05f2ea4552..10fa6990624d 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -264,16 +264,6 @@ namespace clang {
 
 void InitializeImportedDecl(Decl *FromD, Decl *ToD) {
   ToD->IdentifierNamespace = FromD->IdentifierNamespace;
-  if (FromD->hasAttrs())
-for (const Attr *FromAttr : FromD->getAttrs()) {
-  // FIXME: Return of the error here is not possible until store of
-  // import errors is implemented.
-  auto ToAttrOrErr = import(FromAttr);
-  if (ToAttrOrErr)
-ToD->addAttr(*ToAttrOrErr);
-  else
-llvm::consumeError(ToAttrOrErr.takeError());
-}
   if (FromD->isUsed())
 ToD->setIsUsed();
   if (FromD->isImplicit())
@@ -8328,6 +8318,15 @@ Expected ASTImporter::Import(Decl *FromD) {
   // Make sure that ImportImpl registered the imported decl.
   assert(ImportedDecls.count(FromD) != 0 && "Missing call to MapImported?");
 
+  if (FromD->hasAttrs())
+for (const Attr *FromAttr : FromD->getAttrs()) {
+  auto ToAttrOrErr = Import(FromAttr);
+  if (ToAttrOrErr)
+ToD->addAttr(*ToAttrOrErr);
+  else
+return ToAttrOrErr.takeError();
+}
+
   // Notify subclasses.
   Imported(FromD, ToD);
 

diff  --git a/clang/unittests/AST/ASTImporterTest.cpp 
b/clang/unittests/AST/ASTImporterTest.cpp
index e81e5d028cd0..40340cb6f9bc 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -6084,6 +6084,24 @@ TEST_P(CTAD, DeductionGuideShouldCopyALocalTypedef) {
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, CTAD,
 DefaultTestValuesForRunOptions, );
 
+TEST_P(ASTImporterOptionSpecificTestBase, TypedefWithAttribute) {
+  Decl *TU = getTuDecl(
+  R"(
+  namespace N {
+typedef int X __attribute__((annotate("A")));
+  }
+  )",
+  Lang_CXX17, "input.cc");
+  auto *FromD =
+  FirstDeclMatcher().match(TU, typedefDecl(hasName("X")));
+  auto *ToD = Import(FromD, Lang_CXX17);
+  ASSERT_TRUE(ToD);
+  ASSERT_EQ(ToD->getAttrs().size(), 1);
+  auto *ToAttr = dyn_cast(ToD->getAttrs()[0]);
+  ASSERT_TRUE(ToAttr);
+  EXPECT_EQ(ToAttr->getAnnotation(), "A");
+}
+
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
 DefaultTestValuesForRunOptions, );
 



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] f1ca50a - D88665 id 295585 [ASTImporter][AST] Fix structural equivalency crash on dependent FieldDecl

2020-10-16 Thread Gabor Marton via llvm-branch-commits

Author: Gabor Marton
Date: 2020-10-14T11:15:06+02:00
New Revision: f1ca50a5094653463e350daa6c508885f61f11b4

URL: 
https://github.com/llvm/llvm-project/commit/f1ca50a5094653463e350daa6c508885f61f11b4
DIFF: 
https://github.com/llvm/llvm-project/commit/f1ca50a5094653463e350daa6c508885f61f11b4.diff

LOG: D88665 id 295585 [ASTImporter][AST] Fix structural equivalency crash on 
dependent FieldDecl

Added: 


Modified: 
clang/lib/AST/ASTStructuralEquivalence.cpp
clang/unittests/AST/StructuralEquivalenceTest.cpp

Removed: 




diff  --git a/clang/lib/AST/ASTStructuralEquivalence.cpp 
b/clang/lib/AST/ASTStructuralEquivalence.cpp
index 8b5b2444f1e2..3dcd4159dc0b 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -1071,6 +1071,10 @@ static bool 
IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
   }
 
   if (Field1->isBitField()) {
+bool isVD1 = Field1->getBitWidth()->isValueDependent();
+bool isVD2 = Field2->getBitWidth()->isValueDependent();
+if (isVD1 || isVD2)
+  return isVD1 && isVD2;
 // Make sure that the bit-fields are the same length.
 unsigned Bits1 = Field1->getBitWidthValue(Context.FromCtx);
 unsigned Bits2 = Field2->getBitWidthValue(Context.ToCtx);

diff  --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp 
b/clang/unittests/AST/StructuralEquivalenceTest.cpp
index 2b5ce0fed51d..b5aff49eaaee 100644
--- a/clang/unittests/AST/StructuralEquivalenceTest.cpp
+++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp
@@ -906,6 +906,12 @@ TEST_F(StructuralEquivalenceTemplateTest, 
DifferentTemplateArgKind) {
   EXPECT_FALSE(testStructuralMatch(t));
 }
 
+TEST_F(StructuralEquivalenceTemplateTest, DependentFieldDecl) {
+  const char *Code = "template  class foo { int a : sizeof(T); };";
+  auto t = makeNamedDecls(Code, Code, Lang_CXX03);
+  EXPECT_TRUE(testStructuralMatch(t));
+}
+
 TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolSame) {
   auto Decls = makeNamedDecls(
   "template  struct foo {explicit(b) foo(int);};",



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] c7203d1 - [analyzer] Fix crash with pointer to members values

2020-10-16 Thread Gabor Marton via llvm-branch-commits

Author: Valeriy Savchenko
Date: 2020-10-14T11:15:06+02:00
New Revision: c7203d1457dd206b48780d8e3a786b2c1b91b4f0

URL: 
https://github.com/llvm/llvm-project/commit/c7203d1457dd206b48780d8e3a786b2c1b91b4f0
DIFF: 
https://github.com/llvm/llvm-project/commit/c7203d1457dd206b48780d8e3a786b2c1b91b4f0.diff

LOG: [analyzer] Fix crash with pointer to members values

This fix unifies all of the different ways we handled pointer to
members into one.  The crash was caused by the fact that the type
of pointer-to-member values was `void *`, and while this works
for the vast majority of cases it breaks when we actually need
to explain the path for the report.

rdar://problem/64202361

Differential Revision: https://reviews.llvm.org/D85817

Added: 
clang/test/Analysis/PR46264.cpp

Modified: 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
clang/lib/StaticAnalyzer/Core/SVals.cpp
clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
clang/test/Analysis/pointer-to-member.cpp

Removed: 




diff  --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
index a001c0dc7030..142b1ab11750 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
@@ -79,11 +79,11 @@ class LazyCompoundValData : public llvm::FoldingSetNode {
 };
 
 class PointerToMemberData : public llvm::FoldingSetNode {
-  const DeclaratorDecl *D;
+  const NamedDecl *D;
   llvm::ImmutableList L;
 
 public:
-  PointerToMemberData(const DeclaratorDecl *D,
+  PointerToMemberData(const NamedDecl *D,
   llvm::ImmutableList L)
   : D(D), L(L) {}
 
@@ -92,11 +92,11 @@ class PointerToMemberData : public llvm::FoldingSetNode {
   iterator begin() const { return L.begin(); }
   iterator end() const { return L.end(); }
 
-  static void Profile(llvm::FoldingSetNodeID& ID, const DeclaratorDecl *D,
+  static void Profile(llvm::FoldingSetNodeID &ID, const NamedDecl *D,
   llvm::ImmutableList L);
 
-  void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, D, L); }
-  const DeclaratorDecl *getDeclaratorDecl() const {return D;}
+  void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, D, L); }
+  const NamedDecl *getDeclaratorDecl() const { return D; }
 
   llvm::ImmutableList getCXXBaseList() const {
 return L;
@@ -236,9 +236,9 @@ class BasicValueFactory {
   const LazyCompoundValData *getLazyCompoundValData(const StoreRef &store,
 const TypedValueRegion *region);
 
-  const PointerToMemberData *getPointerToMemberData(
-  const DeclaratorDecl *DD,
-  llvm::ImmutableList L);
+  const PointerToMemberData *
+  getPointerToMemberData(const NamedDecl *ND,
+ llvm::ImmutableList L);
 
   llvm::ImmutableList getEmptySValList() {
 return SValListFactory.getEmptyList();

diff  --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index 35ebefdc00d6..4ea85f9730bb 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -233,7 +233,7 @@ class SValBuilder {
const LocationContext *LCtx,
unsigned count);
 
-  DefinedSVal getMemberPointer(const DeclaratorDecl *DD);
+  DefinedSVal getMemberPointer(const NamedDecl *ND);
 
   DefinedSVal getFunctionPointer(const FunctionDecl *func);
 

diff  --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index 1abe29782088..c7fc23c47a30 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -526,7 +526,7 @@ class PointerToMember : public NonLoc {
 
 public:
   using PTMDataType =
-  llvm::PointerUnion;
+  llvm::PointerUnion;
 
   const PTMDataType getPTMData() const {
 return PTMDataType::getFromOpaqueValue(const_cast(Data));
@@ -534,7 +534,7 @@ class PointerToMember : public NonLoc {
 
   bool isNullMemberPointer() const;
 
-  const DeclaratorDecl *getDecl() const;
+  const NamedDecl *getDecl() const;
 
   template
   const AdjustedDecl *getDeclAs() const {

diff  --git a/clang/lib/StaticAnalyzer/Core/BasicValueFactory

[llvm-branch-commits] [clang] 46a1198 - [ASTImporter] Add Visitor for TypedefNameDecl's

2020-10-16 Thread Gabor Marton via llvm-branch-commits

Author: Vince Bridgers
Date: 2020-10-14T11:15:06+02:00
New Revision: 46a1198f805c65fe3f6b1170ad012819e158c1fe

URL: 
https://github.com/llvm/llvm-project/commit/46a1198f805c65fe3f6b1170ad012819e158c1fe
DIFF: 
https://github.com/llvm/llvm-project/commit/46a1198f805c65fe3f6b1170ad012819e158c1fe.diff

LOG: [ASTImporter] Add Visitor for TypedefNameDecl's

We found a case where Typedef Name Declarations were not being added
correctly when importing builtin types. This exposed the need for a
TypedefNameDecl visitor so these types can be added by RecordDecl and
fields.

This code is covered by the ASTImporterTest cases that use the implicit
struct __NSConstantString_tag definitions.

Thanks to @martong for the debugging assist!

Depends on D83970.

Reviewed By: martong

Differential Revision: https://reviews.llvm.org/D83992

Added: 
clang/test/Analysis/Inputs/ctu-import.c
clang/test/Analysis/Inputs/ctu-import.c.externalDefMap.ast-dump.txt
clang/test/Analysis/ctu-implicit.c

Modified: 
clang/lib/AST/ASTImporterLookupTable.cpp

Removed: 




diff  --git a/clang/lib/AST/ASTImporterLookupTable.cpp 
b/clang/lib/AST/ASTImporterLookupTable.cpp
index 4d6fff8f3419..e17d6082dcdc 100644
--- a/clang/lib/AST/ASTImporterLookupTable.cpp
+++ b/clang/lib/AST/ASTImporterLookupTable.cpp
@@ -22,6 +22,20 @@ namespace {
 struct Builder : RecursiveASTVisitor {
   ASTImporterLookupTable <
   Builder(ASTImporterLookupTable <) : LT(LT) {}
+
+  bool VisitTypedefNameDecl(TypedefNameDecl *D) {
+QualType Ty = D->getUnderlyingType();
+Ty = Ty.getCanonicalType();
+if (const auto *RTy = dyn_cast(Ty)) {
+  LT.add(RTy->getAsRecordDecl());
+  // iterate over the field decls, adding them
+  for (auto *it : RTy->getAsRecordDecl()->fields()) {
+LT.add(it);
+  }
+}
+return true;
+  }
+
   bool VisitNamedDecl(NamedDecl *D) {
 LT.add(D);
 return true;

diff  --git a/clang/test/Analysis/Inputs/ctu-import.c 
b/clang/test/Analysis/Inputs/ctu-import.c
new file mode 100644
index ..6c99a3642797
--- /dev/null
+++ b/clang/test/Analysis/Inputs/ctu-import.c
@@ -0,0 +1,15 @@
+
+// Use an internal, implicitly defined type, called by
+// a function imported for CTU. This should not crash.
+int foo(void);
+int foobar(int skip) {
+  __NSConstantString str = {.flags = 1};
+
+  if (str.flags >= 0)
+str.flags = 0;
+  return 4;
+}
+
+int testStaticImplicit(void) {
+  return foobar(3);
+}

diff  --git 
a/clang/test/Analysis/Inputs/ctu-import.c.externalDefMap.ast-dump.txt 
b/clang/test/Analysis/Inputs/ctu-import.c.externalDefMap.ast-dump.txt
new file mode 100644
index ..83d3b4ca451e
--- /dev/null
+++ b/clang/test/Analysis/Inputs/ctu-import.c.externalDefMap.ast-dump.txt
@@ -0,0 +1 @@
+c:@F@testStaticImplicit ctu-import.c.ast

diff  --git a/clang/test/Analysis/ctu-implicit.c 
b/clang/test/Analysis/ctu-implicit.c
new file mode 100644
index ..925044845e09
--- /dev/null
+++ b/clang/test/Analysis/ctu-implicit.c
@@ -0,0 +1,20 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir2
+// RUN: %clang_cc1  \
+// RUN:   -emit-pch -o %t/ctudir2/ctu-import.c.ast %S/Inputs/ctu-import.c
+// RUN: cp %S/Inputs/ctu-import.c.externalDefMap.ast-dump.txt 
%t/ctudir2/externalDefMap.txt
+// RUN: %clang_cc1 -analyze \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config  display-ctu-progress=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir2 \
+// RUN:   -verify %s
+
+void clang_analyzer_eval(int);
+
+int testStaticImplicit(void);
+int func(void) {
+  int ret = testStaticImplicit();
+  clang_analyzer_eval(ret == 4); // expected-warning{{TRUE}}
+  return testStaticImplicit();
+}



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] 70eb2ce - [ASTImporter] Support import of CXXDeductionGuideDecl

2020-11-30 Thread Gabor Marton via llvm-branch-commits

Author: Gabor Marton
Date: 2020-11-30T17:55:25+01:00
New Revision: 70eb2ce395be1fe39ceede6719aa667658d1e5a3

URL: 
https://github.com/llvm/llvm-project/commit/70eb2ce395be1fe39ceede6719aa667658d1e5a3
DIFF: 
https://github.com/llvm/llvm-project/commit/70eb2ce395be1fe39ceede6719aa667658d1e5a3.diff

LOG: [ASTImporter] Support import of CXXDeductionGuideDecl

CXXDeductionGuideDecl is a FunctionDecl, but its constructor should be called
appropriately, at least to set the kind variable properly.

Differential Revision: https://reviews.llvm.org/D92109

Added: 


Modified: 
clang/lib/AST/ASTImporter.cpp
clang/unittests/AST/ASTImporterTest.cpp

Removed: 




diff  --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 01ee8d275af1..1b014314996b 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -499,6 +499,7 @@ namespace clang {
 ExpectedDecl VisitCXXConstructorDecl(CXXConstructorDecl *D);
 ExpectedDecl VisitCXXDestructorDecl(CXXDestructorDecl *D);
 ExpectedDecl VisitCXXConversionDecl(CXXConversionDecl *D);
+ExpectedDecl VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D);
 ExpectedDecl VisitFieldDecl(FieldDecl *D);
 ExpectedDecl VisitIndirectFieldDecl(IndirectFieldDecl *D);
 ExpectedDecl VisitFriendDecl(FriendDecl *D);
@@ -3328,6 +3329,17 @@ ExpectedDecl 
ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
   return ToPOrErr.takeError();
   }
 
+  // Common code to import an explicit specifier of 
diff erent kind of functions.
+  auto ImportExplicitExpr = [this, &Err](auto *Fun) -> ExpectedExpr {
+Expr *ExplicitExpr = nullptr;
+if (Fun->getExplicitSpecifier().getExpr()) {
+  ExplicitExpr = importChecked(Err, Fun->getExplicitSpecifier().getExpr());
+  if (Err)
+return std::move(Err);
+}
+return ExplicitExpr;
+  };
+
   // Create the imported function.
   FunctionDecl *ToFunction = nullptr;
   if (auto *FromConstructor = dyn_cast(D)) {
@@ -3369,17 +3381,13 @@ ExpectedDecl 
ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
 ToDtor->setOperatorDelete(ToOperatorDelete, ToThisArg);
   } else if (CXXConversionDecl *FromConversion =
  dyn_cast(D)) {
-Expr *ExplicitExpr = nullptr;
-if (FromConversion->getExplicitSpecifier().getExpr()) {
-  auto Imp = import(FromConversion->getExplicitSpecifier().getExpr());
-  if (!Imp)
-return Imp.takeError();
-  ExplicitExpr = *Imp;
-}
+ExpectedExpr ExplicitExpr = ImportExplicitExpr(FromConversion);
+if (!ExplicitExpr)
+  return ExplicitExpr.takeError();
 if (GetImportedOrCreateDecl(
 ToFunction, D, Importer.getToContext(), cast(DC),
 ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(),
-ExplicitSpecifier(ExplicitExpr,
+ExplicitSpecifier(*ExplicitExpr,
   
FromConversion->getExplicitSpecifier().getKind()),
 D->getConstexprKind(), SourceLocation(), TrailingRequiresClause))
   return ToFunction;
@@ -3390,6 +3398,18 @@ ExpectedDecl 
ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
 Method->isInlineSpecified(), D->getConstexprKind(),
 SourceLocation(), TrailingRequiresClause))
   return ToFunction;
+  } else if (auto *Guide = dyn_cast(D)) {
+ExpectedExpr ExplicitExpr = ImportExplicitExpr(Guide);
+if (!ExplicitExpr)
+  return ExplicitExpr.takeError();
+if (GetImportedOrCreateDecl(
+ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart,
+ExplicitSpecifier(*ExplicitExpr,
+  Guide->getExplicitSpecifier().getKind()),
+NameInfo, T, TInfo, ToEndLoc))
+  return ToFunction;
+cast(ToFunction)
+->setIsCopyDeductionCandidate(Guide->isCopyDeductionCandidate());
   } else {
 if (GetImportedOrCreateDecl(
 ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart,
@@ -3517,6 +3537,11 @@ ExpectedDecl 
ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) {
   return VisitCXXMethodDecl(D);
 }
 
+ExpectedDecl
+ASTNodeImporter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
+  return VisitFunctionDecl(D);
+}
+
 ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
   // Import the major distinguishing characteristics of a variable.
   DeclContext *DC, *LexicalDC;

diff  --git a/clang/unittests/AST/ASTImporterTest.cpp 
b/clang/unittests/AST/ASTImporterTest.cpp
index 81a92a10f48d..7e56b3ed501f 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -5957,6 +5957,47 @@ TEST_P(ImportWithExternalSource, 
CompleteRecordBeforeImporting) {
   EXPECT_EQ(Record, CompletedTags.front());
 }
 
+TEST_P(ImportFunctions, CTADImplicit) {
+  Decl *FromTU = getTuDecl(
+  R"(
+  template  struct A {
+A(T);
+  };

[llvm-branch-commits] [clang] b40b319 - [analyzer][StdLibraryFunctionsChecker] Add return value constraint to functions with BufferSize

2020-12-02 Thread Gabor Marton via llvm-branch-commits

Author: Gabor Marton
Date: 2020-12-02T17:54:48+01:00
New Revision: b40b3196b32110f00b7610851f4ef182ac751ba0

URL: 
https://github.com/llvm/llvm-project/commit/b40b3196b32110f00b7610851f4ef182ac751ba0
DIFF: 
https://github.com/llvm/llvm-project/commit/b40b3196b32110f00b7610851f4ef182ac751ba0.diff

LOG: [analyzer][StdLibraryFunctionsChecker] Add return value constraint to 
functions with BufferSize

Differential Revision: https://reviews.llvm.org/D92474

Added: 


Modified: 
clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index f8eafde3218d..8a34950ce734 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -457,6 +457,10 @@ class StdLibraryFunctionsChecker
   CaseConstraints.push_back(std::move(CS));
   return *this;
 }
+Summary &Case(const ConstraintSet &CS) {
+  CaseConstraints.push_back(CS);
+  return *this;
+}
 Summary &ArgConstraint(ValueConstraintPtr VC) {
   assert(VC->getArgNo() != Ret &&
  "Arg constraint should not refer to the return value");
@@ -1235,9 +1239,8 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
   // read()-like functions that never return more than buffer size.
   auto FreadSummary =
   Summary(NoEvalCall)
-  .Case({
-  ReturnValueCondition(LessThanOrEq, ArgNo(2)),
-  })
+  .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
+ ReturnValueCondition(WithinRange, Range(0, SizeMax))})
   .ArgConstraint(NotNull(ArgNo(0)))
   .ArgConstraint(NotNull(ArgNo(3)))
   .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1),
@@ -1764,6 +1767,8 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
 Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy},
   RetType{Ssize_tTy}),
 Summary(NoEvalCall)
+.Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
+   ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
 .ArgConstraint(NotNull(ArgNo(0)))
 .ArgConstraint(NotNull(ArgNo(1)))
 .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
@@ -1779,6 +1784,8 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
 ArgTypes{IntTy, ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy},
 RetType{Ssize_tTy}),
 Summary(NoEvalCall)
+.Case({ReturnValueCondition(LessThanOrEq, ArgNo(3)),
+   ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
 .ArgConstraint(NotNull(ArgNo(1)))
 .ArgConstraint(NotNull(ArgNo(2)))
@@ -1842,6 +1849,9 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
 Optional Socklen_tPtrRestrictTy = getRestrictTy(Socklen_tPtrTy);
 Optional Socklen_tMax = getMaxValue(Socklen_tTy);
 
+const auto ReturnsZeroOrMinusOne =
+ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, 0))};
+
 // In 'socket.h' of some libc implementations with C99, sockaddr parameter
 // is a transparent union of the underlying sockaddr_ family of pointers
 // instead of being a pointer to struct sockaddr. In these cases, the
@@ -1850,6 +1860,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
 // constraints which require pointer types for the sockaddr param.
 auto Accept =
 Summary(NoEvalCall)
+.Case({ReturnValueCondition(WithinRange, Range(-1, IntMax))})
 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, 
IntMax)));
 if (!addToFunctionSummaryMap(
 "accept",
@@ -1872,6 +1883,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
 Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy},
   RetType{IntTy}),
 Summary(NoEvalCall)
+.Case(ReturnsZeroOrMinusOne)
 .ArgConstraint(
 ArgumentCondition(0, WithinRange, Range(0, IntMax)))
 .ArgConstraint(NotNull(ArgNo(1)))
@@ -1884,6 +1896,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
   "bind",
   Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}),
   Summary(NoEvalCall)
+  .Case(ReturnsZeroOrMinusOne)
   .ArgConstraint(
   ArgumentCondition(0, WithinRange, Range(0, IntMax)))
   .ArgConstraint(
@@ -1897,6 +1910,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
Socklen_tPtrRestrictTy},
   Ret

[llvm-branch-commits] [clang] 1e14588 - [Clang][Sema] Attempt to fix CTAD faulty copy of non-local typedefs

2020-12-03 Thread Gabor Marton via llvm-branch-commits

Author: Gabor Marton
Date: 2020-12-03T11:35:47+01:00
New Revision: 1e14588d0f6845976e774c87a18a84a0f7b61015

URL: 
https://github.com/llvm/llvm-project/commit/1e14588d0f6845976e774c87a18a84a0f7b61015
DIFF: 
https://github.com/llvm/llvm-project/commit/1e14588d0f6845976e774c87a18a84a0f7b61015.diff

LOG: [Clang][Sema] Attempt to fix CTAD faulty copy of non-local typedefs

http://lists.llvm.org/pipermail/cfe-dev/2020-November/067252.html

Differential Revision: https://reviews.llvm.org/D92101

Added: 


Modified: 
clang/lib/Sema/SemaTemplate.cpp
clang/unittests/AST/ASTImporterTest.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 5b321bb74400..5710f9e3daad 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -2077,27 +2077,28 @@ class ExtractTypeForDeductionGuide
   QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) {
 ASTContext &Context = SemaRef.getASTContext();
 TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl();
-TypeLocBuilder InnerTLB;
-QualType Transformed =
-TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc());
-TypeSourceInfo *TSI =
-TransformType(InnerTLB.getTypeSourceInfo(Context, Transformed));
-
-TypedefNameDecl *Decl = nullptr;
-
-if (isa(OrigDecl))
-  Decl = TypeAliasDecl::Create(
-  Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
-  OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
-else {
-  assert(isa(OrigDecl) && "Not a Type alias or typedef");
-  Decl = TypedefDecl::Create(
-  Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
-  OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
+TypedefNameDecl *Decl = OrigDecl;
+// Transform the underlying type of the typedef and clone the Decl only if
+// the typedef has a dependent context.
+if (OrigDecl->getDeclContext()->isDependentContext()) {
+  TypeLocBuilder InnerTLB;
+  QualType Transformed =
+  TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc());
+  TypeSourceInfo *TSI =
+  TransformType(InnerTLB.getTypeSourceInfo(Context, Transformed));
+  if (isa(OrigDecl))
+Decl = TypeAliasDecl::Create(
+Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
+OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
+  else {
+assert(isa(OrigDecl) && "Not a Type alias or typedef");
+Decl = TypedefDecl::Create(
+Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
+OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
+  }
+  MaterializedTypedefs.push_back(Decl);
 }
 
-MaterializedTypedefs.push_back(Decl);
-
 QualType TDTy = Context.getTypedefType(Decl);
 TypedefTypeLoc TypedefTL = TLB.push(TDTy);
 TypedefTL.setNameLoc(TL.getNameLoc());

diff  --git a/clang/unittests/AST/ASTImporterTest.cpp 
b/clang/unittests/AST/ASTImporterTest.cpp
index 7e56b3ed501f..e4c73a832a14 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -5998,6 +5998,77 @@ TEST_P(ImportFunctions, CTADUserDefinedExplicit) {
   EXPECT_TRUE(ToD->isExplicit());
 }
 
+// FIXME Move these tests out of ASTImporterTest. For that we need to factor
+// out the ASTImporter specific pars from ASTImporterOptionSpecificTestBase
+// into a new test Fixture. Then we should lift up this Fixture to its own
+// implementation file and only then could we reuse the Fixture in other AST
+// unitttests.
+struct CTAD : ASTImporterOptionSpecificTestBase {};
+
+TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedef) {
+  Decl *TU = getTuDecl(
+  R"(
+  typedef int U;
+  template  struct A {
+A(U, T);
+  };
+  A a{(int)0, (int)0};
+  )",
+  Lang_CXX17, "input.cc");
+  auto *Guide = FirstDeclMatcher().match(
+  TU, cxxDeductionGuideDecl());
+  auto *Typedef = FirstDeclMatcher().match(
+  TU, typedefNameDecl(hasName("U")));
+  ParmVarDecl *Param = Guide->getParamDecl(0);
+  // The type of the first param (which is a typedef) should match the typedef
+  // in the global scope.
+  EXPECT_EQ(Param->getType()->getAs()->getDecl(), Typedef);
+}
+
+TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedefInParamPtr) {
+  Decl *TU = getTuDecl(
+  R"(
+  typedef int U;
+  template  struct A {
+A(U*, T);
+  };
+  A a{(int*)0, (int)0};
+  )",
+  Lang_CXX17, "input.cc");
+  auto *Guide = FirstDeclMatcher().match(
+  TU, cxxDeductionGuideDecl());
+  auto *Typedef = FirstDeclMatcher().match(
+  TU, typedefNameDecl(hasName("U")));
+  ParmVarDecl *Param = Guide->getParamDecl(0);
+  EXPECT_EQ(Param->getType()
+->getAs()
+

[llvm-branch-commits] [clang] d14c631 - [analyzer][StdLibraryFunctionsChecker] Make close and mmap to accept -1 as fd

2020-12-08 Thread Gabor Marton via llvm-branch-commits

Author: Gabor Marton
Date: 2020-12-08T16:58:30+01:00
New Revision: d14c63167315edfc4a4ad91fac9c866c6e0cb67f

URL: 
https://github.com/llvm/llvm-project/commit/d14c63167315edfc4a4ad91fac9c866c6e0cb67f
DIFF: 
https://github.com/llvm/llvm-project/commit/d14c63167315edfc4a4ad91fac9c866c6e0cb67f.diff

LOG: [analyzer][StdLibraryFunctionsChecker] Make close and mmap to accept -1 as 
fd

close:
It is quite often that users chose to call close even if the fd is
negative. Theoretically, it would be nicer to close only valid fds, but
in practice the implementations of close just returns with EBADF in case
of a non-valid fd param. So, we can eliminate many false positives if we
let close to take -1 as an fd. Other negative values are very unlikely,
because open and other fd factories return with -1 in case of failure.

mmap:
In the case of MAP_ANONYMOUS flag (which is supported e.g. in Linux) the
mapping is not backed by any file; its contents are initialized to zero.
The fd argument is ignored; however, some implementations require fd to
be -1 if MAP_ANONYMOUS (or MAP_ANON) is specified, and portable
applications should ensure this.
Consequently, we must allow -1 as the 4th arg.

Differential Revision: https://reviews.llvm.org/D92764

Added: 


Modified: 
clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 8a34950ce7341..de825b2fee11f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -1672,7 +1672,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
 addToFunctionSummaryMap("close", Signature(ArgTypes{IntTy}, 
RetType{IntTy}),
 Summary(NoEvalCall)
 .ArgConstraint(ArgumentCondition(
-0, WithinRange, Range(0, IntMax;
+0, WithinRange, Range(-1, IntMax;
 
 // long fpathconf(int fildes, int name);
 addToFunctionSummaryMap("fpathconf",
@@ -1734,7 +1734,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
 Summary(NoEvalCall)
 .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, 
SizeMax)))
 .ArgConstraint(
-ArgumentCondition(4, WithinRange, Range(0, IntMax;
+ArgumentCondition(4, WithinRange, Range(-1, IntMax;
 
 Optional Off64_tTy = lookupTy("off64_t");
 // void *mmap64(void *addr, size_t length, int prot, int flags, int fd,
@@ -1746,7 +1746,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
 Summary(NoEvalCall)
 .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, 
SizeMax)))
 .ArgConstraint(
-ArgumentCondition(4, WithinRange, Range(0, IntMax;
+ArgumentCondition(4, WithinRange, Range(-1, IntMax;
 
 // int pipe(int fildes[2]);
 addToFunctionSummaryMap(



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] febe750 - [analyzer][StdLibraryFunctionsChecker] Add more return value contraints

2020-12-08 Thread Gabor Marton via llvm-branch-commits

Author: Gabor Marton
Date: 2020-12-08T17:04:29+01:00
New Revision: febe75032f6f8322cce1dcbba11a44559aaa14e3

URL: 
https://github.com/llvm/llvm-project/commit/febe75032f6f8322cce1dcbba11a44559aaa14e3
DIFF: 
https://github.com/llvm/llvm-project/commit/febe75032f6f8322cce1dcbba11a44559aaa14e3.diff

LOG: [analyzer][StdLibraryFunctionsChecker] Add more return value contraints

This time, we add contraints to functions that either return with [0, -1] or
with a file descriptor.

Differential Revision: https://reviews.llvm.org/D92771

Added: 


Modified: 
clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index de825b2fee11..f0710a658148 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -1322,21 +1322,31 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
 .ArgConstraint(ArgumentCondition(
 0, WithinRange, Range(0, LongMax;
 
+const auto ReturnsZeroOrMinusOne =
+ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, 0))};
+const auto ReturnsFileDescriptor =
+ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, IntMax))};
+
 // int access(const char *pathname, int amode);
 addToFunctionSummaryMap(
 "access", Signature(ArgTypes{ConstCharPtrTy, IntTy}, RetType{IntTy}),
-Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0;
+Summary(NoEvalCall)
+.Case(ReturnsZeroOrMinusOne)
+.ArgConstraint(NotNull(ArgNo(0;
 
 // int faccessat(int dirfd, const char *pathname, int mode, int flags);
 addToFunctionSummaryMap(
 "faccessat",
 Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, IntTy},
   RetType{IntTy}),
-Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(1;
+Summary(NoEvalCall)
+.Case(ReturnsZeroOrMinusOne)
+.ArgConstraint(NotNull(ArgNo(1;
 
 // int dup(int fildes);
 addToFunctionSummaryMap("dup", Signature(ArgTypes{IntTy}, RetType{IntTy}),
 Summary(NoEvalCall)
+.Case(ReturnsFileDescriptor)
 .ArgConstraint(ArgumentCondition(
 0, WithinRange, Range(0, IntMax;
 
@@ -1344,6 +1354,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
 addToFunctionSummaryMap(
 "dup2", Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
 Summary(NoEvalCall)
+.Case(ReturnsFileDescriptor)
 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
 .ArgConstraint(
 ArgumentCondition(1, WithinRange, Range(0, IntMax;
@@ -1352,6 +1363,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
 addToFunctionSummaryMap("fdatasync",
 Signature(ArgTypes{IntTy}, RetType{IntTy}),
 Summary(NoEvalCall)
+.Case(ReturnsZeroOrMinusOne)
 .ArgConstraint(ArgumentCondition(
 0, WithinRange, Range(0, IntMax;
 
@@ -1367,6 +1379,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
 // int fsync(int fildes);
 addToFunctionSummaryMap("fsync", Signature(ArgTypes{IntTy}, 
RetType{IntTy}),
 Summary(NoEvalCall)
+.Case(ReturnsZeroOrMinusOne)
 .ArgConstraint(ArgumentCondition(
 0, WithinRange, Range(0, IntMax;
 
@@ -1376,13 +1389,16 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
 addToFunctionSummaryMap(
 "truncate",
 Signature(ArgTypes{ConstCharPtrTy, Off_tTy}, RetType{IntTy}),
-Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0;
+Summary(NoEvalCall)
+.Case(ReturnsZeroOrMinusOne)
+.ArgConstraint(NotNull(ArgNo(0;
 
 // int symlink(const char *oldpath, const char *newpath);
 addToFunctionSummaryMap(
 "symlink",
 Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{IntTy}),
 Summary(NoEvalCall)
+.Case(ReturnsZeroOrMinusOne)
 .ArgConstraint(NotNull(ArgNo(0)))
 .ArgConstraint(NotNull(ArgNo(1;
 
@@ -1392,6 +1408,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
 Signature(ArgTypes{ConstCharPtrTy, IntTy, ConstCharPtrTy},
   RetType{IntTy}),
 Summary(NoEvalCall)
+.Case(ReturnsZeroOrMinusOne)
 .ArgConstraint(NotNul

[llvm-branch-commits] [clang] a5e6590 - [ASTImporter] Support CXXDeductionGuideDecl with local typedef

2020-12-09 Thread Gabor Marton via llvm-branch-commits

Author: Gabor Marton
Date: 2020-12-09T21:25:04+01:00
New Revision: a5e6590b15b17793d7a82f8b39998381acb73109

URL: 
https://github.com/llvm/llvm-project/commit/a5e6590b15b17793d7a82f8b39998381acb73109
DIFF: 
https://github.com/llvm/llvm-project/commit/a5e6590b15b17793d7a82f8b39998381acb73109.diff

LOG: [ASTImporter] Support CXXDeductionGuideDecl with local typedef

CXXDeductionGuideDecl with a local typedef has its own copy of the
TypedefDecl with the CXXDeductionGuideDecl as the DeclContext of that
TypedefDecl.
```
  template  struct A {
typedef T U;
A(U, T);
  };
  A a{(int)0, (int)0};
```
Related discussion on cfe-dev:
http://lists.llvm.org/pipermail/cfe-dev/2020-November/067252.html

Without this fix, when we import the CXXDeductionGuideDecl (via
VisitFunctionDecl) then before creating the Decl we must import the
FunctionType. However, the first parameter's type is the afore mentioned
local typedef. So, we then start importing the TypedefDecl whose
DeclContext is the CXXDeductionGuideDecl itself. The infinite loop is
formed.
```
 #0 
clang::ASTNodeImporter::VisitCXXDeductionGuideDecl(clang::CXXDeductionGuideDecl*)
 clang/lib/AST/ASTImporter.cpp:3543:0
 #1 clang::declvisitor::Base >::Visit(clang::Decl*) 
/home/egbomrt/WORK/llvm5/build/debug/tools/clang/include/clang/AST/DeclNodes.inc:405:0
 #2 clang::ASTImporter::ImportImpl(clang::Decl*) 
clang/lib/AST/ASTImporter.cpp:8038:0
 #3 clang::ASTImporter::Import(clang::Decl*) 
clang/lib/AST/ASTImporter.cpp:8200:0
 #4 clang::ASTImporter::ImportContext(clang::DeclContext*) 
clang/lib/AST/ASTImporter.cpp:8297:0
 #5 clang::ASTNodeImporter::ImportDeclContext(clang::Decl*, 
clang::DeclContext*&, clang::DeclContext*&) clang/lib/AST/ASTImporter.cpp:1852:0
 #6 clang::ASTNodeImporter::ImportDeclParts(clang::NamedDecl*, 
clang::DeclContext*&, clang::DeclContext*&, clang::DeclarationName&, 
clang::NamedDecl*&, clang::SourceLocation&) clang/lib/AST/ASTImporter.cpp:1628:0
 #7 clang::ASTNodeImporter::VisitTypedefNameDecl(clang::TypedefNameDecl*, bool) 
clang/lib/AST/ASTImporter.cpp:2419:0
 #8 clang::ASTNodeImporter::VisitTypedefDecl(clang::TypedefDecl*) 
clang/lib/AST/ASTImporter.cpp:2500:0
 #9 clang::declvisitor::Base >::Visit(clang::Decl*) 
/home/egbomrt/WORK/llvm5/build/debug/tools/clang/include/clang/AST/DeclNodes.inc:315:0
 #10 clang::ASTImporter::ImportImpl(clang::Decl*) 
clang/lib/AST/ASTImporter.cpp:8038:0
 #11 clang::ASTImporter::Import(clang::Decl*) 
clang/lib/AST/ASTImporter.cpp:8200:0
 #12 llvm::Expected 
clang::ASTNodeImporter::import(clang::TypedefNameDecl*) 
clang/lib/AST/ASTImporter.cpp:165:0
 #13 clang::ASTNodeImporter::VisitTypedefType(clang::TypedefType const*) 
clang/lib/AST/ASTImporter.cpp:1304:0
 #14 clang::TypeVisitor 
>::Visit(clang::Type const*) 
/home/egbomrt/WORK/llvm5/build/debug/tools/clang/include/clang/AST/TypeNodes.inc:74:0
 #15 clang::ASTImporter::Import(clang::QualType) 
clang/lib/AST/ASTImporter.cpp:8071:0
 #16 llvm::Expected 
clang::ASTNodeImporter::import(clang::QualType const&) 
clang/lib/AST/ASTImporter.cpp:179:0
 #17 clang::ASTNodeImporter::VisitFunctionProtoType(clang::FunctionProtoType 
const*) clang/lib/AST/ASTImporter.cpp:1244:0
 #18 clang::TypeVisitor 
>::Visit(clang::Type const*) 
/home/egbomrt/WORK/llvm5/build/debug/tools/clang/include/clang/AST/TypeNodes.inc:47:0
 #19 clang::ASTImporter::Import(clang::QualType) 
clang/lib/AST/ASTImporter.cpp:8071:0
 #20 llvm::Expected 
clang::ASTNodeImporter::import(clang::QualType const&) 
clang/lib/AST/ASTImporter.cpp:179:0
 #21 clang::QualType 
clang::ASTNodeImporter::importChecked(llvm::Error&, 
clang::QualType const&) clang/lib/AST/ASTImporter.cpp:198:0
 #22 clang::ASTNodeImporter::VisitFunctionDecl(clang::FunctionDecl*) 
clang/lib/AST/ASTImporter.cpp:3313:0
 #23 
clang::ASTNodeImporter::VisitCXXDeductionGuideDecl(clang::CXXDeductionGuideDecl*)
 clang/lib/AST/ASTImporter.cpp:3543:0
```

The fix is to first create the TypedefDecl and only then start to import
the DeclContext.
Basically, we could do this during the import of all other Decls (not
just for typedefs). But it seems, there is only one another AST
construct that has a similar cycle: a struct defined as a function
parameter:
```
int struct_in_proto(struct data_t{int a;int b;} *d);

```
In that case, however, we had decided to return simply with an error
back then because that seemed to be a very rare construct.

Differential Revision: https://reviews.llvm.org/D92209

Added: 


Modified: 
clang/lib/AST/ASTImporter.cpp
clang/unittests/AST/ASTImporterTest.cpp

Removed: 




diff  --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 50632efc281f..ea05f2ea4552 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -388,6 +388,8 @@ namespace clang {
 ExpectedType VisitObjCObjectPointerType(const ObjCObjectPointerType *T);
 
 // Importing declarations
+Err