[PATCH] D53979: [analyzer][CTU] Correctly signal in the function index generation tool if there was an error

2018-11-01 Thread Gabor Marton via Phabricator via cfe-commits
martong accepted this revision.
martong added a comment.
This revision is now accepted and ready to land.

Looks good to me. It is great to see that we can get rid of so many header and 
lib dependencies.


https://reviews.llvm.org/D53979



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


[PATCH] D53697: [ASTImporter][Structural Eq] Check for isBeingDefined

2018-10-30 Thread Gabor Marton via Phabricator via cfe-commits
martong marked 2 inline comments as done.
martong added a comment.

> I wonder if it is possible to get into situation where non-equivalent decls 
> are marked equivalent with this patch? If yes, we can create a mapping 
> between decls being imported and original decls as an alternative solution. 
> However, I cannot find any counterexample.

I don't think so.

This change is the natural extension what we already do (in line 1021 and 1022) 
with `getDefinition()`.
`getDefinition()` works just as we would expect with a simple `RecordDecl`: 
`getDefinition()` returns a non-nullptr if `isBeingDefined()` is true.
However, `getDefinition()` may return a non-nullptr if `D` is a `CXXRecordDecl` 
even if `D` is being defined.

  CXXRecordDecl *getDefinition() const {
// We only need an update if we don't already know which
// declaration is the definition.
auto *DD = DefinitionData ? DefinitionData : dataPtr();
return DD ? DD->Definition : nullptr;
  }

This all depends on whether `DefinitionData` is set. And we do set that during 
`ImportDefinition(RecordDecl *,)`.
And then we start importing methods and fields of the `CXXRecordDecl` via 
`ImportDeclContext` before the call to `completeDefinition()` which sets 
`IsBeingDefined`.
During those imports, the `getDefinition()` of a `CXXRecordDecl` will return 
with a non-nullptr value and we would go on checking the fields, but we are in 
the middle of importing the fields (or methods).




Comment at: lib/AST/ASTStructuralEquivalence.cpp:1037
+  // equality and we assume that the decls are equal.
+  if (D1->isBeingDefined() || D2->isBeingDefined())
+return true;

a_sidorin wrote:
> Is it worth it to assert if only one Decl should be in `isBeingDefined()` 
> state at time?
Strictly speaking `D1` will always come from the "From" context and such it 
should report true for `isBeingDefined`. But the structural equivalence logic  
should be independent from the import logic ideally, so I would not add that 
assert.



Comment at: unittests/AST/ASTImporterTest.cpp:3729
 
+TEST_P(ASTImporterTestBase, ImportingTypedefShouldImportTheCompleteType) {
+  // We already have an incomplete underlying type in the "To" context.

a_sidorin wrote:
> Looks like this test is from another patch (D53693)?
Yes, exactly, good catch, I just removed it.


Repository:
  rC Clang

https://reviews.llvm.org/D53697



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


[PATCH] D53697: [ASTImporter][Structural Eq] Check for isBeingDefined

2018-10-30 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 171723.
martong marked 2 inline comments as done.
martong added a comment.

- Remove unrelated test


Repository:
  rC Clang

https://reviews.llvm.org/D53697

Files:
  lib/AST/ASTStructuralEquivalence.cpp
  unittests/AST/ASTImporterTest.cpp


Index: unittests/AST/ASTImporterTest.cpp
===
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -3726,6 +3726,45 @@
   EXPECT_EQ(To1->getPreviousDecl(), To0);
 }
 
+TEST_P(ASTImporterTestBase,
+ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
+  {
+Decl *FromTU = getTuDecl(
+R"(
+template 
+struct B;
+)",
+Lang_CXX, "input0.cc");
+auto *FromD = FirstDeclMatcher().match(
+FromTU, classTemplateDecl(hasName("B")));
+
+Import(FromD, Lang_CXX);
+  }
+
+  {
+Decl *FromTU = getTuDecl(
+R"(
+template 
+struct B {
+  void f();
+  B* b;
+};
+)",
+Lang_CXX, "input1.cc");
+FunctionDecl *FromD = FirstDeclMatcher().match(
+FromTU, functionDecl(hasName("f")));
+Import(FromD, Lang_CXX);
+auto *FromCTD = FirstDeclMatcher().match(
+FromTU, classTemplateDecl(hasName("B")));
+auto *ToCTD = cast(Import(FromCTD, Lang_CXX));
+EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
+
+// We expect no (ODR) warning during the import.
+auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
+  }
+}
+
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
 ::testing::Values(ArgVector()), );
 
Index: lib/AST/ASTStructuralEquivalence.cpp
===
--- lib/AST/ASTStructuralEquivalence.cpp
+++ lib/AST/ASTStructuralEquivalence.cpp
@@ -1016,7 +1016,8 @@
 return false;
 
   // Compare the definitions of these two records. If either or both are
-  // incomplete, we assume that they are equivalent.
+  // incomplete (i.e. it is a forward decl), we assume that they are
+  // equivalent.
   D1 = D1->getDefinition();
   D2 = D2->getDefinition();
   if (!D1 || !D2)
@@ -1031,6 +1032,11 @@
 if (D1->hasExternalLexicalStorage() || D2->hasExternalLexicalStorage())
   return true;
 
+  // If one definition is currently being defined, we do not compare for
+  // equality and we assume that the decls are equal.
+  if (D1->isBeingDefined() || D2->isBeingDefined())
+return true;
+
   if (auto *D1CXX = dyn_cast(D1)) {
 if (auto *D2CXX = dyn_cast(D2)) {
   if (D1CXX->hasExternalLexicalStorage() &&


Index: unittests/AST/ASTImporterTest.cpp
===
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -3726,6 +3726,45 @@
   EXPECT_EQ(To1->getPreviousDecl(), To0);
 }
 
+TEST_P(ASTImporterTestBase,
+ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
+  {
+Decl *FromTU = getTuDecl(
+R"(
+template 
+struct B;
+)",
+Lang_CXX, "input0.cc");
+auto *FromD = FirstDeclMatcher().match(
+FromTU, classTemplateDecl(hasName("B")));
+
+Import(FromD, Lang_CXX);
+  }
+
+  {
+Decl *FromTU = getTuDecl(
+R"(
+template 
+struct B {
+  void f();
+  B* b;
+};
+)",
+Lang_CXX, "input1.cc");
+FunctionDecl *FromD = FirstDeclMatcher().match(
+FromTU, functionDecl(hasName("f")));
+Import(FromD, Lang_CXX);
+auto *FromCTD = FirstDeclMatcher().match(
+FromTU, classTemplateDecl(hasName("B")));
+auto *ToCTD = cast(Import(FromCTD, Lang_CXX));
+EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
+
+// We expect no (ODR) warning during the import.
+auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
+  }
+}
+
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
 ::testing::Values(ArgVector()), );
 
Index: lib/AST/ASTStructuralEquivalence.cpp
===
--- lib/AST/ASTStructuralEquivalence.cpp
+++ lib/AST/ASTStructuralEquivalence.cpp
@@ -1016,7 +1016,8 @@
 return false;
 
   // Compare the definitions of these two records. If either or both are
-  // incomplete, we assume that they are equivalent.
+  // incomplete (i.e. it is a forward decl), we assume that they are
+  // equivalent.
   D1 = D1->getDefinition();
   D2 = D2->getDefinition();
   if (!D1 || !D2)
@@ -1031,6 +1032,11 @@
 if (D1->hasExternalLexicalStorage() || D2->hasExternalLexicalStorage())
   return true;
 
+  // If one definition is currently being defined, we do not 

[PATCH] D53693: [ASTImporter] Typedef import brings in the complete type

2018-10-25 Thread Gabor Marton via Phabricator via cfe-commits
martong created this revision.
martong added a reviewer: a_sidorin.
Herald added subscribers: cfe-commits, Szelethus, dkrupp, rnkovacs.
Herald added a reviewer: a.sidorin.

When we already have an incomplete underlying type of a typedef in the
"To" context, and the "From" context has the same typedef, but the
underlying type is complete, then the imported type should be complete.

Fixes an assertion in Xerces:
Assertion `DD && "queried property of class with no definition"' failed.
This assert is happening in the analyzer engine, because that attempts
to query an underlying type of a typedef, which happens to be
incomplete.


Repository:
  rC Clang

https://reviews.llvm.org/D53693

Files:
  lib/AST/ASTImporter.cpp
  unittests/AST/ASTImporterTest.cpp


Index: unittests/AST/ASTImporterTest.cpp
===
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -3726,6 +3726,38 @@
   EXPECT_EQ(To1->getPreviousDecl(), To0);
 }
 
+TEST_P(ASTImporterTestBase, ImportingTypedefShouldImportTheCompleteType) {
+  // We already have an incomplete underlying type in the "To" context.
+  auto Code =
+  R"(
+  template 
+  struct S {
+void foo();
+  };
+  using U = S;
+  )";
+  Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
+  auto *ToD = FirstDeclMatcher().match(ToTU,
+  typedefNameDecl(hasName("U")));
+  ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
+
+  // The "From" context has the same typedef, but the underlying type is
+  // complete this time.
+  Decl *FromTU = getTuDecl(std::string(Code) +
+  R"(
+  void foo(U* u) {
+u->foo();
+  }
+  )", Lang_CXX11);
+  auto *FromD = FirstDeclMatcher().match(FromTU,
+  typedefNameDecl(hasName("U")));
+  ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
+
+  // The imported type should be complete.
+  auto *ImportedD = cast(Import(FromD, Lang_CXX11));
+  EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
+}
+
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
 ::testing::Values(ArgVector()), );
 
Index: lib/AST/ASTImporter.cpp
===
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -2306,8 +2306,14 @@
 continue;
   if (auto *FoundTypedef = dyn_cast(FoundDecl)) {
 if (Importer.IsStructurallyEquivalent(
-D->getUnderlyingType(), FoundTypedef->getUnderlyingType()))
+D->getUnderlyingType(), FoundTypedef->getUnderlyingType())) {
+  QualType FromUT = D->getUnderlyingType();
+  QualType FoundUT = FoundTypedef->getUnderlyingType();
+  // If the "From" context has a complete underlying type but we
+  // already have a complete underlying type then return with that.
+  if (!FromUT->isIncompleteType() && !FoundUT->isIncompleteType())
 return Importer.MapImported(D, FoundTypedef);
+}
   }
 
   ConflictingDecls.push_back(FoundDecl);


Index: unittests/AST/ASTImporterTest.cpp
===
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -3726,6 +3726,38 @@
   EXPECT_EQ(To1->getPreviousDecl(), To0);
 }
 
+TEST_P(ASTImporterTestBase, ImportingTypedefShouldImportTheCompleteType) {
+  // We already have an incomplete underlying type in the "To" context.
+  auto Code =
+  R"(
+  template 
+  struct S {
+void foo();
+  };
+  using U = S;
+  )";
+  Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
+  auto *ToD = FirstDeclMatcher().match(ToTU,
+  typedefNameDecl(hasName("U")));
+  ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
+
+  // The "From" context has the same typedef, but the underlying type is
+  // complete this time.
+  Decl *FromTU = getTuDecl(std::string(Code) +
+  R"(
+  void foo(U* u) {
+u->foo();
+  }
+  )", Lang_CXX11);
+  auto *FromD = FirstDeclMatcher().match(FromTU,
+  typedefNameDecl(hasName("U")));
+  ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
+
+  // The imported type should be complete.
+  auto *ImportedD = cast(Import(FromD, Lang_CXX11));
+  EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
+}
+
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
 ::testing::Values(ArgVector()), );
 
Index: lib/AST/ASTImporter.cpp
===
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -2306,8 +2306,14 @@
 continue;
   if (auto *FoundTypedef = dyn_cast(FoundDecl)) {
 if (Importer.IsStructurallyEquivalent(
-D->getUnderlyingType(), FoundTypedef->getUnderlyingType()))
+D->getUnderlyingType(), FoundTypedef->getUnderlyingType())) {
+  QualType FromUT = 

[PATCH] D53697: [Structural Eq] Check for isBeingDefined

2018-10-25 Thread Gabor Marton via Phabricator via cfe-commits
martong created this revision.
martong added a reviewer: a_sidorin.
Herald added subscribers: cfe-commits, Szelethus, dkrupp, rnkovacs.
martong added a dependency: D53693: [ASTImporter] Typedef import brings in the 
complete type.

If one definition is currently being defined, we do not compare for
equality and we assume that the decls are equal.


Repository:
  rC Clang

https://reviews.llvm.org/D53697

Files:
  lib/AST/ASTStructuralEquivalence.cpp
  unittests/AST/ASTImporterTest.cpp

Index: unittests/AST/ASTImporterTest.cpp
===
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -3726,6 +3726,77 @@
   EXPECT_EQ(To1->getPreviousDecl(), To0);
 }
 
+TEST_P(ASTImporterTestBase, ImportingTypedefShouldImportTheCompleteType) {
+  // We already have an incomplete underlying type in the "To" context.
+  auto Code =
+  R"(
+  template 
+  struct S {
+void foo();
+  };
+  using U = S;
+  )";
+  Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
+  auto *ToD = FirstDeclMatcher().match(ToTU,
+  typedefNameDecl(hasName("U")));
+  ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
+
+  // The "From" context has the same typedef, but the underlying type is
+  // complete this time.
+  Decl *FromTU = getTuDecl(std::string(Code) +
+  R"(
+  void foo(U* u) {
+u->foo();
+  }
+  )", Lang_CXX11);
+  auto *FromD = FirstDeclMatcher().match(FromTU,
+  typedefNameDecl(hasName("U")));
+  ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
+
+  // The imported type should be complete.
+  auto *ImportedD = cast(Import(FromD, Lang_CXX11));
+  EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
+}
+
+TEST_P(ASTImporterTestBase,
+ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
+  {
+Decl *FromTU = getTuDecl(
+R"(
+template 
+struct B;
+)",
+Lang_CXX, "input0.cc");
+auto *FromD = FirstDeclMatcher().match(
+FromTU, classTemplateDecl(hasName("B")));
+
+Import(FromD, Lang_CXX);
+  }
+
+  {
+Decl *FromTU = getTuDecl(
+R"(
+template 
+struct B {
+  void f();
+  B* b;
+};
+)",
+Lang_CXX, "input1.cc");
+FunctionDecl *FromD = FirstDeclMatcher().match(
+FromTU, functionDecl(hasName("f")));
+Import(FromD, Lang_CXX);
+auto *FromCTD = FirstDeclMatcher().match(
+FromTU, classTemplateDecl(hasName("B")));
+auto *ToCTD = cast(Import(FromCTD, Lang_CXX));
+EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
+
+// We expect no (ODR) warning during the import.
+auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
+  }
+}
+
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
 ::testing::Values(ArgVector()), );
 
Index: lib/AST/ASTStructuralEquivalence.cpp
===
--- lib/AST/ASTStructuralEquivalence.cpp
+++ lib/AST/ASTStructuralEquivalence.cpp
@@ -1016,7 +1016,8 @@
 return false;
 
   // Compare the definitions of these two records. If either or both are
-  // incomplete, we assume that they are equivalent.
+  // incomplete (i.e. it is a forward decl), we assume that they are
+  // equivalent.
   D1 = D1->getDefinition();
   D2 = D2->getDefinition();
   if (!D1 || !D2)
@@ -1031,6 +1032,11 @@
 if (D1->hasExternalLexicalStorage() || D2->hasExternalLexicalStorage())
   return true;
 
+  // If one definition is currently being defined, we do not compare for
+  // equality and we assume that the decls are equal.
+  if (D1->isBeingDefined() || D2->isBeingDefined())
+return true;
+
   if (auto *D1CXX = dyn_cast(D1)) {
 if (auto *D2CXX = dyn_cast(D2)) {
   if (D1CXX->hasExternalLexicalStorage() &&
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53699: [ASTImporter] Fix inequality of functions with different attributes

2018-10-25 Thread Gabor Marton via Phabricator via cfe-commits
martong created this revision.
martong added a reviewer: a_sidorin.
Herald added subscribers: cfe-commits, Szelethus, dkrupp, rnkovacs.
Herald added a reviewer: a.sidorin.

FunctionType::ExtInfo holds such properties of a function which are needed
mostly for code gen. We should not compare these bits when checking for
structural equivalency.
Checking ExtInfo caused false ODR errors during CTU analysis (of tmux).


Repository:
  rC Clang

https://reviews.llvm.org/D53699

Files:
  lib/AST/ASTStructuralEquivalence.cpp
  unittests/AST/StructuralEquivalenceTest.cpp


Index: unittests/AST/StructuralEquivalenceTest.cpp
===
--- unittests/AST/StructuralEquivalenceTest.cpp
+++ unittests/AST/StructuralEquivalenceTest.cpp
@@ -370,6 +370,15 @@
   EXPECT_FALSE(testStructuralMatch(t));
 }
 
+TEST_F(StructuralEquivalenceFunctionTest,
+FunctionsWithDifferentAttributesButSameTypesShouldBeEqual) {
+  auto t = makeNamedDecls(
+  "__attribute__((noreturn)) void foo();",
+  "  void foo();",
+  Lang_C);
+  EXPECT_TRUE(testStructuralMatch(t));
+}
+
 struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {
 };
 
Index: lib/AST/ASTStructuralEquivalence.cpp
===
--- lib/AST/ASTStructuralEquivalence.cpp
+++ lib/AST/ASTStructuralEquivalence.cpp
@@ -540,8 +540,6 @@
 if (!IsStructurallyEquivalent(Context, Function1->getReturnType(),
   Function2->getReturnType()))
   return false;
-if (Function1->getExtInfo() != Function2->getExtInfo())
-  return false;
 break;
   }
 


Index: unittests/AST/StructuralEquivalenceTest.cpp
===
--- unittests/AST/StructuralEquivalenceTest.cpp
+++ unittests/AST/StructuralEquivalenceTest.cpp
@@ -370,6 +370,15 @@
   EXPECT_FALSE(testStructuralMatch(t));
 }
 
+TEST_F(StructuralEquivalenceFunctionTest,
+FunctionsWithDifferentAttributesButSameTypesShouldBeEqual) {
+  auto t = makeNamedDecls(
+  "__attribute__((noreturn)) void foo();",
+  "  void foo();",
+  Lang_C);
+  EXPECT_TRUE(testStructuralMatch(t));
+}
+
 struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {
 };
 
Index: lib/AST/ASTStructuralEquivalence.cpp
===
--- lib/AST/ASTStructuralEquivalence.cpp
+++ lib/AST/ASTStructuralEquivalence.cpp
@@ -540,8 +540,6 @@
 if (!IsStructurallyEquivalent(Context, Function1->getReturnType(),
   Function2->getReturnType()))
   return false;
-if (Function1->getExtInfo() != Function2->getExtInfo())
-  return false;
 break;
   }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53702: [ASTImporter] Set redecl chain of functions before any other import

2018-10-25 Thread Gabor Marton via Phabricator via cfe-commits
martong created this revision.
martong added a reviewer: a_sidorin.
Herald added subscribers: cfe-commits, Szelethus, dkrupp, rnkovacs.
Herald added a reviewer: a.sidorin.

FunctionDecl import starts with a lookup and then we create a new Decl.
Then in case of CXXConstructorDecl we further import other Decls
(base classes, members through CXXConstructorDecl::inits()) before connecting
the redecl chain.  During those in-between imports structural eq fails
because the canonical decl is different.  This commit fixes this.
Synthesizing a test seemed extremely hard, however, Xerces analysis
reproduces the problem.


Repository:
  rC Clang

https://reviews.llvm.org/D53702

Files:
  lib/AST/ASTImporter.cpp


Index: lib/AST/ASTImporter.cpp
===
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -3139,19 +3139,6 @@
 FromConstructor->isExplicit(),
 D->isInlineSpecified(), D->isImplicit(), D->isConstexpr()))
   return ToFunction;
-if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) {
-  SmallVector CtorInitializers(NumInitializers);
-  // Import first, then allocate memory and copy if there was no error.
-  if (Error Err = ImportContainerChecked(
-  FromConstructor->inits(), CtorInitializers))
-return std::move(Err);
-  auto **Memory =
-  new (Importer.getToContext()) CXXCtorInitializer *[NumInitializers];
-  std::copy(CtorInitializers.begin(), CtorInitializers.end(), Memory);
-  auto *ToCtor = cast(ToFunction);
-  ToCtor->setCtorInitializers(Memory);
-  ToCtor->setNumCtorInitializers(NumInitializers);
-}
   } else if (isa(D)) {
 if (GetImportedOrCreateDecl(
 ToFunction, D, Importer.getToContext(), cast(DC),
@@ -3179,6 +3166,30 @@
   return ToFunction;
   }
 
+  // Connect the redecl chain.
+  if (FoundByLookup) {
+auto *Recent = const_cast(
+  FoundByLookup->getMostRecentDecl());
+ToFunction->setPreviousDecl(Recent);
+  }
+
+  // Import Ctor initializers.
+  if (auto *FromConstructor = dyn_cast(D)) {
+if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) {
+  SmallVector CtorInitializers(NumInitializers);
+  // Import first, then allocate memory and copy if there was no error.
+  if (Error Err = ImportContainerChecked(
+  FromConstructor->inits(), CtorInitializers))
+return std::move(Err);
+  auto **Memory =
+  new (Importer.getToContext()) CXXCtorInitializer *[NumInitializers];
+  std::copy(CtorInitializers.begin(), CtorInitializers.end(), Memory);
+  auto *ToCtor = cast(ToFunction);
+  ToCtor->setCtorInitializers(Memory);
+  ToCtor->setNumCtorInitializers(NumInitializers);
+}
+  }
+
   ToFunction->setQualifierInfo(ToQualifierLoc);
   ToFunction->setAccess(D->getAccess());
   ToFunction->setLexicalDeclContext(LexicalDC);
@@ -3194,12 +3205,6 @@
   }
   ToFunction->setParams(Parameters);
 
-  if (FoundByLookup) {
-auto *Recent = const_cast(
-  FoundByLookup->getMostRecentDecl());
-ToFunction->setPreviousDecl(Recent);
-  }
-
   // We need to complete creation of FunctionProtoTypeLoc manually with setting
   // params it refers to.
   if (TInfo) {


Index: lib/AST/ASTImporter.cpp
===
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -3139,19 +3139,6 @@
 FromConstructor->isExplicit(),
 D->isInlineSpecified(), D->isImplicit(), D->isConstexpr()))
   return ToFunction;
-if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) {
-  SmallVector CtorInitializers(NumInitializers);
-  // Import first, then allocate memory and copy if there was no error.
-  if (Error Err = ImportContainerChecked(
-  FromConstructor->inits(), CtorInitializers))
-return std::move(Err);
-  auto **Memory =
-  new (Importer.getToContext()) CXXCtorInitializer *[NumInitializers];
-  std::copy(CtorInitializers.begin(), CtorInitializers.end(), Memory);
-  auto *ToCtor = cast(ToFunction);
-  ToCtor->setCtorInitializers(Memory);
-  ToCtor->setNumCtorInitializers(NumInitializers);
-}
   } else if (isa(D)) {
 if (GetImportedOrCreateDecl(
 ToFunction, D, Importer.getToContext(), cast(DC),
@@ -3179,6 +3166,30 @@
   return ToFunction;
   }
 
+  // Connect the redecl chain.
+  if (FoundByLookup) {
+auto *Recent = const_cast(
+  FoundByLookup->getMostRecentDecl());
+ToFunction->setPreviousDecl(Recent);
+  }
+
+  // Import Ctor initializers.
+  if (auto *FromConstructor = dyn_cast(D)) {
+if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) {
+  SmallVector CtorInitializers(NumInitializers);
+  // Import first, then allocate memory and copy if there was no error.
+  if (Error Err = ImportContainerChecked(
+  

[PATCH] D53704: [ASTImporter] Import overrides before importing the rest of the chain

2018-10-25 Thread Gabor Marton via Phabricator via cfe-commits
martong created this revision.
martong added a reviewer: a_sidorin.
Herald added subscribers: cfe-commits, Szelethus, dkrupp, rnkovacs.
Herald added a reviewer: a.sidorin.

During method import we check for structural eq of two methods.
In the structural eq check we check for their isVirtual() flag. That
flag, however, may depend on the number of overrides. Before this
change we imported the overrides *after* we had imported the rest of the
redecl chain.  So, during the import of another decl from the chain
IsVirtual() gave false result.

Writing tests for this is not really possible, because there is no way
to remove an overridden method via the AST API.
(We should access the private ASTContext::OverriddenMethods container.)
Also, we should do the remove in the middle of the import process.


Repository:
  rC Clang

https://reviews.llvm.org/D53704

Files:
  lib/AST/ASTImporter.cpp


Index: lib/AST/ASTImporter.cpp
===
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -3258,16 +3258,16 @@
 DC->makeDeclVisibleInContext(ToFunction);
   }
 
+  if (auto *FromCXXMethod = dyn_cast(D))
+ImportOverrides(cast(ToFunction), FromCXXMethod);
+
   // Import the rest of the chain. I.e. import all subsequent declarations.
   for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) {
 ExpectedDecl ToRedeclOrErr = import(*RedeclIt);
 if (!ToRedeclOrErr)
   return ToRedeclOrErr.takeError();
   }
 
-  if (auto *FromCXXMethod = dyn_cast(D))
-ImportOverrides(cast(ToFunction), FromCXXMethod);
-
   return ToFunction;
 }
 


Index: lib/AST/ASTImporter.cpp
===
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -3258,16 +3258,16 @@
 DC->makeDeclVisibleInContext(ToFunction);
   }
 
+  if (auto *FromCXXMethod = dyn_cast(D))
+ImportOverrides(cast(ToFunction), FromCXXMethod);
+
   // Import the rest of the chain. I.e. import all subsequent declarations.
   for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) {
 ExpectedDecl ToRedeclOrErr = import(*RedeclIt);
 if (!ToRedeclOrErr)
   return ToRedeclOrErr.takeError();
   }
 
-  if (auto *FromCXXMethod = dyn_cast(D))
-ImportOverrides(cast(ToFunction), FromCXXMethod);
-
   return ToFunction;
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53708: [ASTImporter] Add importer specific lookup

2018-10-25 Thread Gabor Marton via Phabricator via cfe-commits
martong created this revision.
martong added a reviewer: a_sidorin.
Herald added subscribers: cfe-commits, Szelethus, dkrupp, rnkovacs, mgorny.
Herald added a reviewer: a.sidorin.

There are certain cases when normal C/C++ lookup (localUncachedLookup)
does not find AST nodes. E.g.:

Example 1:

  template 
  struct X {
friend void foo(); // this is never found in the DC of the TU.
  };

Example 2:

  // The fwd decl to Foo is not found in the lookupPtr of the DC of the
  // translation unit decl.
  struct A { struct Foo *p; };

In these cases we create a new node instead of returning with the old one.
To fix it we create a new lookup table which holds every node and we are
not interested in any C++ specific visibility considerations.
Simply, we must know if there is an existing Decl in a given DC.


Repository:
  rC Clang

https://reviews.llvm.org/D53708

Files:
  include/clang/AST/ASTImporter.h
  include/clang/AST/ASTImporterLookupTable.h
  include/clang/CrossTU/CrossTranslationUnit.h
  lib/AST/ASTImporter.cpp
  lib/AST/ASTImporterLookupTable.cpp
  lib/AST/CMakeLists.txt
  lib/CrossTU/CrossTranslationUnit.cpp
  lib/Frontend/ASTMerge.cpp
  tools/clang-import-test/clang-import-test.cpp
  unittests/AST/ASTImporterTest.cpp

Index: unittests/AST/ASTImporterTest.cpp
===
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -14,6 +14,7 @@
 #include "MatchVerifier.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTImporter.h"
+#include "clang/AST/ASTImporterLookupTable.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/Tooling.h"
@@ -306,24 +307,26 @@
   Unit->enableSourceFileDiagnostics();
 }
 
-void lazyInitImporter(ASTUnit *ToAST) {
+void lazyInitImporter(ASTImporterLookupTable , ASTUnit *ToAST) {
   assert(ToAST);
   if (!Importer) {
 Importer.reset(new ASTImporter(
-ToAST->getASTContext(), ToAST->getFileManager(),
+, ToAST->getASTContext(), ToAST->getFileManager(),
 Unit->getASTContext(), Unit->getFileManager(), false));
   }
   assert(>getASTContext() == >getToContext());
   createVirtualFileIfNeeded(ToAST, FileName, Code);
 }
 
-Decl *import(ASTUnit *ToAST, Decl *FromDecl) {
-  lazyInitImporter(ToAST);
+Decl *import(ASTImporterLookupTable , ASTUnit *ToAST,
+ Decl *FromDecl) {
+  lazyInitImporter(LookupTable, ToAST);
   return Importer->Import(FromDecl);
- }
+}
 
-QualType import(ASTUnit *ToAST, QualType FromType) {
-  lazyInitImporter(ToAST);
+QualType import(ASTImporterLookupTable , ASTUnit *ToAST,
+QualType FromType) {
+  lazyInitImporter(LookupTable, ToAST);
   return Importer->Import(FromType);
 }
   };
@@ -337,13 +340,24 @@
   // vector is expanding, with the list we won't have these issues.
   std::list FromTUs;
 
-  void lazyInitToAST(Language ToLang) {
+  // Initialize the lookup table if not initialized already.
+  void lazyInitLookupTable(TranslationUnitDecl *ToTU) {
+assert(ToTU);
+if (LookupTablePtr)
+  return;
+LookupTablePtr = llvm::make_unique(*ToTU);
+  }
+
+  void lazyInitToAST(Language ToLang, StringRef ToSrcCode, StringRef FileName) {
 if (ToAST)
   return;
 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
+// Source code must be a valid live buffer through the tests lifetime.
+ToCode = ToSrcCode;
 // Build the AST from an empty file.
-ToAST = tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
+ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, FileName);
 ToAST->enableSourceFileDiagnostics();
+lazyInitLookupTable(ToAST->getASTContext().getTranslationUnitDecl());
   }
 
   TU *findFromTU(Decl *From) {
@@ -357,6 +371,10 @@
 return &*It;
   }
 
+protected:
+
+  std::unique_ptr LookupTablePtr;
+
 public:
   // We may have several From context but only one To context.
   std::unique_ptr ToAST;
@@ -373,26 +391,23 @@
 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
 TU  = FromTUs.back();
 
-ToCode = ToSrcCode;
 assert(!ToAST);
-ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
-ToAST->enableSourceFileDiagnostics();
+lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
 
 ASTContext  = FromTU.Unit->getASTContext();
 
-createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
-
 IdentifierInfo *ImportedII = (Identifier);
 assert(ImportedII && "Declaration with the given identifier "
  "should be specified in test!");
 DeclarationName ImportDeclName(ImportedII);
-SmallVector FoundDecls;
+SmallVector FoundDecls;
 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
   

[PATCH] D51533: [ASTImporter] Merge ExprBits

2018-09-03 Thread Gabor Marton via Phabricator via cfe-commits
martong added inline comments.



Comment at: unittests/AST/ASTImporterTest.cpp:3241
+  auto *ToD = Import(FromD, Lang_CXX11);
+  ASSERT_TRUE(ToD);
+  auto *ToInitExpr = cast(ToD)->getAnyInitializer();

a_sidorin wrote:
> EXPECT_TRUE (same below).
Thanks, changed it.


Repository:
  rL LLVM

https://reviews.llvm.org/D51533



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


[PATCH] D51533: [ASTImporter] Merge ExprBits

2018-09-03 Thread Gabor Marton via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
martong marked an inline comment as done.
Closed by commit rL341316: [ASTImporter] Merge ExprBits (authored by martong, 
committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D51533?vs=163494=163707#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D51533

Files:
  cfe/trunk/lib/AST/ASTImporter.cpp
  cfe/trunk/unittests/AST/ASTImporterTest.cpp


Index: cfe/trunk/lib/AST/ASTImporter.cpp
===
--- cfe/trunk/lib/AST/ASTImporter.cpp
+++ cfe/trunk/lib/AST/ASTImporter.cpp
@@ -6817,9 +6817,9 @@
 To->setSyntacticForm(ToSyntForm);
   }
 
+  // Copy InitListExprBitfields, which are not handled in the ctor of
+  // InitListExpr.
   To->sawArrayRangeDesignator(ILE->hadArrayRangeDesignator());
-  To->setValueDependent(ILE->isValueDependent());
-  To->setInstantiationDependent(ILE->isInstantiationDependent());
 
   return To;
 }
@@ -7164,6 +7164,19 @@
   if (!ToS)
 return nullptr;
 
+  if (auto *ToE = dyn_cast(ToS)) {
+auto *FromE = cast(FromS);
+// Copy ExprBitfields, which may not be handled in Expr subclasses
+// constructors.
+ToE->setValueKind(FromE->getValueKind());
+ToE->setObjectKind(FromE->getObjectKind());
+ToE->setTypeDependent(FromE->isTypeDependent());
+ToE->setValueDependent(FromE->isValueDependent());
+ToE->setInstantiationDependent(FromE->isInstantiationDependent());
+ToE->setContainsUnexpandedParameterPack(
+FromE->containsUnexpandedParameterPack());
+  }
+
   // Record the imported declaration.
   ImportedStmts[FromS] = ToS;
   return ToS;
Index: cfe/trunk/unittests/AST/ASTImporterTest.cpp
===
--- cfe/trunk/unittests/AST/ASTImporterTest.cpp
+++ cfe/trunk/unittests/AST/ASTImporterTest.cpp
@@ -3225,6 +3225,25 @@
   
unless(classTemplatePartialSpecializationDecl();
 }
 
+TEST_P(ASTImporterTestBase, InitListExprValueKindShouldBeImported) {
+  Decl *TU = getTuDecl(
+  R"(
+  const int ();
+  void foo() { const int {init()}; }
+  )", Lang_CXX11, "input0.cc");
+  auto *FromD = FirstDeclMatcher().match(TU, varDecl(hasName("a")));
+  ASSERT_TRUE(FromD->getAnyInitializer());
+  auto *InitExpr = FromD->getAnyInitializer();
+  ASSERT_TRUE(InitExpr);
+  ASSERT_TRUE(InitExpr->isGLValue());
+
+  auto *ToD = Import(FromD, Lang_CXX11);
+  EXPECT_TRUE(ToD);
+  auto *ToInitExpr = cast(ToD)->getAnyInitializer();
+  EXPECT_TRUE(ToInitExpr);
+  EXPECT_TRUE(ToInitExpr->isGLValue());
+}
+
 struct DeclContextTest : ASTImporterTestBase {};
 
 TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {


Index: cfe/trunk/lib/AST/ASTImporter.cpp
===
--- cfe/trunk/lib/AST/ASTImporter.cpp
+++ cfe/trunk/lib/AST/ASTImporter.cpp
@@ -6817,9 +6817,9 @@
 To->setSyntacticForm(ToSyntForm);
   }
 
+  // Copy InitListExprBitfields, which are not handled in the ctor of
+  // InitListExpr.
   To->sawArrayRangeDesignator(ILE->hadArrayRangeDesignator());
-  To->setValueDependent(ILE->isValueDependent());
-  To->setInstantiationDependent(ILE->isInstantiationDependent());
 
   return To;
 }
@@ -7164,6 +7164,19 @@
   if (!ToS)
 return nullptr;
 
+  if (auto *ToE = dyn_cast(ToS)) {
+auto *FromE = cast(FromS);
+// Copy ExprBitfields, which may not be handled in Expr subclasses
+// constructors.
+ToE->setValueKind(FromE->getValueKind());
+ToE->setObjectKind(FromE->getObjectKind());
+ToE->setTypeDependent(FromE->isTypeDependent());
+ToE->setValueDependent(FromE->isValueDependent());
+ToE->setInstantiationDependent(FromE->isInstantiationDependent());
+ToE->setContainsUnexpandedParameterPack(
+FromE->containsUnexpandedParameterPack());
+  }
+
   // Record the imported declaration.
   ImportedStmts[FromS] = ToS;
   return ToS;
Index: cfe/trunk/unittests/AST/ASTImporterTest.cpp
===
--- cfe/trunk/unittests/AST/ASTImporterTest.cpp
+++ cfe/trunk/unittests/AST/ASTImporterTest.cpp
@@ -3225,6 +3225,25 @@
   unless(classTemplatePartialSpecializationDecl();
 }
 
+TEST_P(ASTImporterTestBase, InitListExprValueKindShouldBeImported) {
+  Decl *TU = getTuDecl(
+  R"(
+  const int ();
+  void foo() { const int {init()}; }
+  )", Lang_CXX11, "input0.cc");
+  auto *FromD = FirstDeclMatcher().match(TU, varDecl(hasName("a")));
+  ASSERT_TRUE(FromD->getAnyInitializer());
+  auto *InitExpr = FromD->getAnyInitializer();
+  ASSERT_TRUE(InitExpr);
+  ASSERT_TRUE(InitExpr->isGLValue());
+
+  auto *ToD = Import(FromD, Lang_CXX11);
+  EXPECT_TRUE(ToD);
+  auto *ToInitExpr = cast(ToD)->getAnyInitializer();
+  EXPECT_TRUE(ToInitExpr);
+  EXPECT_TRUE(ToInitExpr->isGLValue());
+}
+
 struct 

[PATCH] D51597: [ASTImporter] Fix import of VarDecl init

2018-09-03 Thread Gabor Marton via Phabricator via cfe-commits
martong created this revision.
martong added reviewers: a_sidorin, xazax.hun, r.stahl.
Herald added subscribers: cfe-commits, dkrupp, rnkovacs.
Herald added a reviewer: a.sidorin.
Herald added a reviewer: a.sidorin.

The init expression of a VarDecl is overwritten in the "To" context if we
import a VarDecl without an init expression (and with a definition).  Please
refer to the added tests, especially InitAndDefinitionAreInDifferentTUs.  This
patch fixes the malfunction by importing the whole Decl chain similarly as we
did that in case of FunctionDecls.  We handle the init expression similarly to
a  definition, alas only one init expression will be in the merged ast.


Repository:
  rC Clang

https://reviews.llvm.org/D51597

Files:
  lib/AST/ASTImporter.cpp
  unittests/AST/ASTImporterTest.cpp

Index: unittests/AST/ASTImporterTest.cpp
===
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -1828,13 +1828,62 @@
   {
 Decl *FromTU =
 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
-auto *FromD =
-FirstDeclMatcher().match(FromTU, functionDecl());
+auto *FromD = FirstDeclMatcher().match(
+FromTU, functionDecl(hasName("f")));
 Import(FromD, Lang_CXX);
   }
   EXPECT_TRUE(Imported2->isUsed(false));
 }
 
+TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag2) {
+  auto Pattern = varDecl(hasName("x"));
+  VarDecl *ExistingD;
+  {
+Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
+ExistingD = FirstDeclMatcher().match(ToTU, Pattern);
+  }
+  EXPECT_FALSE(ExistingD->isUsed(false));
+  {
+Decl *FromTU = getTuDecl(
+"int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
+auto *FromD = FirstDeclMatcher().match(
+FromTU, functionDecl(hasName("f")));
+Import(FromD, Lang_CXX);
+  }
+  EXPECT_TRUE(ExistingD->isUsed(false));
+}
+
+TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag3) {
+  auto Pattern = varDecl(hasName("a"));
+  VarDecl *ExistingD;
+  {
+Decl *ToTU = getToTuDecl(
+R"(
+struct A {
+  static const int a = 1;
+};
+)", Lang_CXX);
+ExistingD = FirstDeclMatcher().match(ToTU, Pattern);
+  }
+  EXPECT_FALSE(ExistingD->isUsed(false));
+  {
+Decl *FromTU = getTuDecl(
+R"(
+struct A {
+  static const int a = 1;
+};
+const int *f() { return ::a; } // requires storage,
+ // thus used flag will be set
+)", Lang_CXX, "input1.cc");
+auto *FromFunD = FirstDeclMatcher().match(
+FromTU, functionDecl(hasName("f")));
+auto *FromD = FirstDeclMatcher().match(FromTU, Pattern);
+ASSERT_TRUE(FromD->isUsed(false));
+Import(FromFunD, Lang_CXX);
+  }
+  EXPECT_TRUE(ExistingD->isUsed(false));
+}
+
 TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) {
   auto Pattern = varDecl(hasName("x"));
 
@@ -3244,6 +3293,94 @@
   EXPECT_TRUE(ToInitExpr->isGLValue());
 }
 
+struct ImportVariables : ASTImporterTestBase {};
+
+TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
+  Decl *FromTU = getTuDecl(
+  R"(
+  struct A {
+static const int a = 1 + 2;
+  };
+  const int A::a;
+  )", Lang_CXX, "input1.cc");
+
+  auto *FromDWithInit = FirstDeclMatcher().match(
+  FromTU, varDecl(hasName("a"))); // Decl with init
+  auto *FromDWithDef = LastDeclMatcher().match(
+  FromTU, varDecl(hasName("a"))); // Decl with definition
+  ASSERT_NE(FromDWithInit, FromDWithDef);
+  ASSERT_EQ(FromDWithDef->getPreviousDecl() ,FromDWithInit);
+
+  auto *ToD0 = cast(Import(FromDWithInit, Lang_CXX11));
+  auto *ToD1 = cast(Import(FromDWithDef, Lang_CXX11));
+  ASSERT_TRUE(ToD0);
+  ASSERT_TRUE(ToD1);
+  EXPECT_NE(ToD0, ToD1);
+  EXPECT_EQ(ToD1->getPreviousDecl() ,ToD0);
+}
+
+TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
+  auto StructA =
+  R"(
+  struct A {
+static const int a = 1 + 2;
+  };
+  )";
+  Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
+  Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
+   "input1.cc");
+
+  auto *FromDWithInit = FirstDeclMatcher().match(
+  FromTU, varDecl(hasName("a"))); // Decl with init
+  auto *FromDWithDef = LastDeclMatcher().match(
+  FromTU, varDecl(hasName("a"))); // Decl with definition
+  ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
+  ASSERT_TRUE(FromDWithInit->getInit());
+  ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
+  ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
+  ASSERT_FALSE(FromDWithDef->getInit());
+
+  auto *ToD = FirstDeclMatcher().match(
+  ToTU, varDecl(hasName("a"))); // Decl with init
+  ASSERT_TRUE(ToD->getInit());
+  ASSERT_FALSE(ToD->getDefinition());
+
+  auto *ImportedD = cast(Import(FromDWithDef, Lang_CXX11));
+  EXPECT_TRUE(ImportedD->getAnyInitializer());
+  

[PATCH] D51597: [ASTImporter] Fix import of VarDecl init

2018-09-03 Thread Gabor Marton via Phabricator via cfe-commits
martong added inline comments.



Comment at: unittests/AST/ASTImporterTest.cpp:3763
 
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
+DefaultTestValuesForRunOptions, );

This hunk has nothing to do with this change, but previously we forgot to 
instantiate these test cases :(



Repository:
  rC Clang

https://reviews.llvm.org/D51597



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


[PATCH] D56936: Fix handling of overriden methods during ASTImport

2019-01-21 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

> @martong the only issue is that I am seeing a regression on 
> Analysis/ctu-main.cpp when I run check-clang. I am going to look into it but 
> if you have any insights that would be helpful.

I am looking into it and will come back with what I have found.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56936/new/

https://reviews.llvm.org/D56936



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


[PATCH] D56936: Fix handling of overriden methods during ASTImport

2019-01-21 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

Hi Shafik, thank you for this patch! Generally it looks quite okay to me, but I 
have a few minor comments.




Comment at: lib/AST/ASTImporter.cpp:3049
+  // Import the body of D and attach that to FoundByLookup.
+  // This should probably be refactored into a function since we do the
+  // same below too.

Could you please do this refactor and remove this sentence from the comment? 
(At line 3208 we repeat the same logic.)



Comment at: unittests/AST/ASTImporterTest.cpp:2243
+  auto BP = cxxMethodDecl(hasName("f"), 
hasParent(cxxRecordDecl(hasName("B";
+  auto DP = cxxMethodDecl(hasName("f"), 
hasParent(cxxRecordDecl(hasName("D";
+

balazske wrote:
> I think names like `BP` and `BFP ` could be better (`P` should stand for 
> "Pattern" and always the last part of the name, so use `BFP` and `BFIsDefP`). 
> And for storing `B::F` a `BF` can be better name than `B`.
I agree. I think the contractions we use in 
`ImportOverriddenMethodTwiceOutOfClassDef` are more consistent.



Comment at: unittests/AST/ASTImporterTest.cpp:2325
+  EXPECT_EQ(DeclCounter().match(ToTU, BFP), 1u);
+  EXPECT_EQ(DeclCounter().match(ToTU, BFPIsDef), 0u);
+

balazske wrote:
> For the out-of-class definition the `hasParent(cxxRecordDecl(hasName("B")))` 
> does not match? (Otherwise this count should be 1.)
That does not match, because `hasParent` matches based on the lexical decl 
context. In the case of the out-of-class definition, the lexical decl context 
is the global namespace (the TranslationUnitDecl). 

However, the semantical decl context of the out-of-class definition is the 
CXXRecordDecl with the name "B". But this relation is not symmetric. The 
definition is not the child (i.e. DeclContext::containsDecl is false) of the 
CXXRecordDecl rather the child of the TranslataionUnitDecl.



Comment at: unittests/AST/ASTImporterTest.cpp:2385
+  EXPECT_EQ(DeclCounter().match(ToTU, BFP), 1u);
+  EXPECT_EQ(DeclCounter().match(ToTU, BFPIsDef), 0u);
+

Perhaps it would make sense to have expectations on `DFP` and on `DFPIsDef` too.



Comment at: unittests/AST/ASTImporterTest.cpp:2393
+
+  // The definition should be out-of-class.
+  EXPECT_NE(ToBFInClass, ToBFOutOfClass);

Perhaps it would make sense to have expectations on `D::f() {}` too. Even 
better could be to have a lambda which takes a few Decls as parameters and does 
the expectations on those.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56936/new/

https://reviews.llvm.org/D56936



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


[PATCH] D56936: Fix handling of overriden methods during ASTImport

2019-01-22 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

I have found some other minor things in the tests.




Comment at: unittests/AST/ASTImporterTest.cpp:2275
+  auto DFDef = cxxMethodDecl(
+  hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
+  auto FDefAll = cxxMethodDecl(hasName("f"), isDefinition());

I think the parent should have `hasName("D")` here. Seems like a copy paste 
error.



Comment at: unittests/AST/ASTImporterTest.cpp:2282
+auto *FromD = FirstDeclMatcher().match(FromTU, DP);
+ImportedD = Import(FromD, Lang_CXX);
+  }

`ImportedD` seems to be unused. (And in the next test case too.)



Comment at: unittests/AST/ASTImporterTest.cpp:2400
+
+  // Check that the redecl chain is intact.
+  EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);

Could we check the redecl chain of `D::f()` too?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56936/new/

https://reviews.llvm.org/D56936



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


[PATCH] D56936: Fix handling of overriden methods during ASTImport

2019-01-23 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

> So the problem is that there are references to ParmVarDecl from inside 
> function body and at import of ParmVarDecl always a new one is created even 
> if there is an already existing (in the existing function prototype)?

Yes. During the import of the body we import a `DeclRefExpr` which refers to a 
`ParmVarDecl` but not the existing one, thus a new is created.

> Maybe it works in VisitParmVarDecl to search for already existing ParmVarDecl 
> (not already imported) and return if found.

Yes it would worth to try, indeed.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56936/new/

https://reviews.llvm.org/D56936



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


[PATCH] D55646: [ASTImporter] Make ODR diagnostics warning by default

2018-12-13 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

The primary reason why want these to be Warnings instead of Errors because 
there are many false positive ODR Errors at the moment. These are not fatal 
errors but there is a maximum error count which once reached the whole process 
(analysis) is aborted.
Usually, such false positives are related to a wrong import of redeclaration 
chains or existing errors in the structural match logic.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55646/new/

https://reviews.llvm.org/D55646



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


[PATCH] D53755: [ASTImporter] Remove import of definition from GetAlreadyImportedOrNull

2018-12-12 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

@shafik

> We need to make sure we are running the lldb test suite before committing and 
> watching the bots to make sure the commit does not break them.

I just have tested this patch on macOS  and there seems to be no regression. 
Linux also seems to be without any regression. Very soon I am going to commit 
and I am going to monitor green.lab.llvm.org/green/view/LLDB/ for sign of any 
failure. I will revert in case of any failure asap.

Thanks for the review!


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53755/new/

https://reviews.llvm.org/D53755



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


[PATCH] D53699: [ASTImporter] Fix inequality of functions with different attributes

2018-12-13 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 178060.
martong marked 2 inline comments as done.
martong added a comment.

- Add more tests and simplify comment


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53699/new/

https://reviews.llvm.org/D53699

Files:
  lib/AST/ASTStructuralEquivalence.cpp
  unittests/AST/StructuralEquivalenceTest.cpp


Index: unittests/AST/StructuralEquivalenceTest.cpp
===
--- unittests/AST/StructuralEquivalenceTest.cpp
+++ unittests/AST/StructuralEquivalenceTest.cpp
@@ -370,6 +370,31 @@
   EXPECT_FALSE(testStructuralMatch(t));
 }
 
+TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentNoreturnAttr) {
+  auto t = makeNamedDecls(
+  "__attribute__((noreturn)) void foo();",
+  "  void foo();",
+  Lang_C);
+  EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest,
+FunctionsWithDifferentCallingConventions) {
+  auto t = makeNamedDecls(
+  "__attribute__((fastcall)) void foo();",
+  "__attribute__((ms_abi))   void foo();",
+  Lang_C);
+  EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentSavedRegsAttr) 
{
+  auto t = makeNamedDecls(
+  "__attribute__((no_caller_saved_registers)) void foo();",
+  "   void foo();",
+  Lang_C);
+  EXPECT_FALSE(testStructuralMatch(t));
+}
+
 struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {
 };
 
Index: lib/AST/ASTStructuralEquivalence.cpp
===
--- lib/AST/ASTStructuralEquivalence.cpp
+++ lib/AST/ASTStructuralEquivalence.cpp
@@ -297,6 +297,32 @@
   return true;
 }
 
+/// Determine structural equivalence based on the ExtInfo of functions. This
+/// is inspired by ASTContext::mergeFunctionTypes(), we compare calling
+/// conventions bits but must not compare some other bits.
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext ,
+ FunctionType::ExtInfo EI1,
+ FunctionType::ExtInfo EI2) {
+  // Compatible functions must have compatible calling conventions.
+  if (EI1.getCC() != EI2.getCC())
+return false;
+
+  // Regparm is part of the calling convention.
+  if (EI1.getHasRegParm() != EI2.getHasRegParm())
+return false;
+  if (EI1.getRegParm() != EI2.getRegParm())
+return false;
+
+  if (EI1.getProducesResult() != EI2.getProducesResult())
+return false;
+  if (EI1.getNoCallerSavedRegs() != EI2.getNoCallerSavedRegs())
+return false;
+  if (EI1.getNoCfCheck() != EI2.getNoCfCheck())
+return false;
+
+  return true;
+}
+
 /// Determine structural equivalence of two types.
 static bool IsStructurallyEquivalent(StructuralEquivalenceContext ,
  QualType T1, QualType T2) {
@@ -540,7 +566,8 @@
 if (!IsStructurallyEquivalent(Context, Function1->getReturnType(),
   Function2->getReturnType()))
   return false;
-if (Function1->getExtInfo() != Function2->getExtInfo())
+if (!IsStructurallyEquivalent(Context, Function1->getExtInfo(),
+  Function2->getExtInfo()))
   return false;
 break;
   }


Index: unittests/AST/StructuralEquivalenceTest.cpp
===
--- unittests/AST/StructuralEquivalenceTest.cpp
+++ unittests/AST/StructuralEquivalenceTest.cpp
@@ -370,6 +370,31 @@
   EXPECT_FALSE(testStructuralMatch(t));
 }
 
+TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentNoreturnAttr) {
+  auto t = makeNamedDecls(
+  "__attribute__((noreturn)) void foo();",
+  "  void foo();",
+  Lang_C);
+  EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest,
+FunctionsWithDifferentCallingConventions) {
+  auto t = makeNamedDecls(
+  "__attribute__((fastcall)) void foo();",
+  "__attribute__((ms_abi))   void foo();",
+  Lang_C);
+  EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentSavedRegsAttr) {
+  auto t = makeNamedDecls(
+  "__attribute__((no_caller_saved_registers)) void foo();",
+  "   void foo();",
+  Lang_C);
+  EXPECT_FALSE(testStructuralMatch(t));
+}
+
 struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {
 };
 
Index: lib/AST/ASTStructuralEquivalence.cpp
===
--- lib/AST/ASTStructuralEquivalence.cpp
+++ lib/AST/ASTStructuralEquivalence.cpp
@@ -297,6 +297,32 @@
   return true;
 }
 
+/// Determine structural equivalence based on the ExtInfo of functions. This
+/// is inspired by ASTContext::mergeFunctionTypes(), we compare calling
+/// conventions 

[PATCH] D53699: [ASTImporter] Fix inequality of functions with different attributes

2018-12-13 Thread Gabor Marton via Phabricator via cfe-commits
martong marked 4 inline comments as done.
martong added inline comments.



Comment at: lib/AST/ASTStructuralEquivalence.cpp:302
+/// is inspired by ASTContext::mergeFunctionTypes(), we compare calling
+/// conventions bits but must not compare some other bits, e.g. the noreturn
+/// bit.

shafik wrote:
> This comment is confusing b/c it looks like the noreturn bits are the only 
> one you are not checking.
Ok, I have removed that part of the comment.



Comment at: unittests/AST/StructuralEquivalenceTest.cpp:373
 
+TEST_F(StructuralEquivalenceFunctionTest,
+FunctionsWithDifferentAttributesButSameTypesShouldBeEqual) {

shafik wrote:
> Can we get some more tests to be a little more thorough and can we also get a 
> test where it is expected to to be false as well?
Ok, I have adder a few more tests and renamed the existing one.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53699/new/

https://reviews.llvm.org/D53699



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


[PATCH] D44100: [ASTImporter] Reorder fields after structure import is finished

2018-12-10 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

Alexey, good news! I have finished the testing of the above patch applied on 
top of 174545. Neither is a regression on Linux nor on macOS. (ASTTests, 
check-clang-astmerge, check-clang-import, check-clang-analysis, check-lldb).


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D44100/new/

https://reviews.llvm.org/D44100



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


[PATCH] D53755: [ASTImporter] Remove import of definition from GetAlreadyImportedOrNull

2018-12-12 Thread Gabor Marton via Phabricator via cfe-commits
This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rL348923: [ASTImporter] Remove import of definition from 
GetAlreadyImportedOrNull (authored by martong, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D53755?vs=175639=177834#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53755/new/

https://reviews.llvm.org/D53755

Files:
  cfe/trunk/include/clang/AST/ASTImporter.h
  cfe/trunk/lib/AST/ASTImporter.cpp


Index: cfe/trunk/include/clang/AST/ASTImporter.h
===
--- cfe/trunk/include/clang/AST/ASTImporter.h
+++ cfe/trunk/include/clang/AST/ASTImporter.h
@@ -209,7 +209,7 @@
 /// Return the copy of the given declaration in the "to" context if
 /// it has already been imported from the "from" context.  Otherwise return
 /// NULL.
-Decl *GetAlreadyImportedOrNull(Decl *FromD);
+Decl *GetAlreadyImportedOrNull(const Decl *FromD) const;
 
 /// Import the given declaration context from the "from"
 /// AST context into the "to" AST context.
Index: cfe/trunk/lib/AST/ASTImporter.cpp
===
--- cfe/trunk/lib/AST/ASTImporter.cpp
+++ cfe/trunk/lib/AST/ASTImporter.cpp
@@ -1580,6 +1580,9 @@
 return Err;
 
   ToD = cast_or_null(Importer.GetAlreadyImportedOrNull(D));
+  if (ToD)
+if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(D, ToD))
+  return Err;
 
   return Error::success();
 }
@@ -7745,17 +7748,12 @@
   return ToAttr;
 }
 
-Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) {
-  llvm::DenseMap::iterator Pos = ImportedDecls.find(FromD);
-  if (Pos != ImportedDecls.end()) {
-Decl *ToD = Pos->second;
-// FIXME: move this call to ImportDeclParts().
-if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(FromD, 
ToD))
-  llvm::consumeError(std::move(Err));
-return ToD;
-  } else {
+Decl *ASTImporter::GetAlreadyImportedOrNull(const Decl *FromD) const {
+  auto Pos = ImportedDecls.find(FromD);
+  if (Pos != ImportedDecls.end())
+return Pos->second;
+  else
 return nullptr;
-  }
 }
 
 Expected ASTImporter::Import_New(Decl *FromD) {


Index: cfe/trunk/include/clang/AST/ASTImporter.h
===
--- cfe/trunk/include/clang/AST/ASTImporter.h
+++ cfe/trunk/include/clang/AST/ASTImporter.h
@@ -209,7 +209,7 @@
 /// Return the copy of the given declaration in the "to" context if
 /// it has already been imported from the "from" context.  Otherwise return
 /// NULL.
-Decl *GetAlreadyImportedOrNull(Decl *FromD);
+Decl *GetAlreadyImportedOrNull(const Decl *FromD) const;
 
 /// Import the given declaration context from the "from"
 /// AST context into the "to" AST context.
Index: cfe/trunk/lib/AST/ASTImporter.cpp
===
--- cfe/trunk/lib/AST/ASTImporter.cpp
+++ cfe/trunk/lib/AST/ASTImporter.cpp
@@ -1580,6 +1580,9 @@
 return Err;
 
   ToD = cast_or_null(Importer.GetAlreadyImportedOrNull(D));
+  if (ToD)
+if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(D, ToD))
+  return Err;
 
   return Error::success();
 }
@@ -7745,17 +7748,12 @@
   return ToAttr;
 }
 
-Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) {
-  llvm::DenseMap::iterator Pos = ImportedDecls.find(FromD);
-  if (Pos != ImportedDecls.end()) {
-Decl *ToD = Pos->second;
-// FIXME: move this call to ImportDeclParts().
-if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(FromD, ToD))
-  llvm::consumeError(std::move(Err));
-return ToD;
-  } else {
+Decl *ASTImporter::GetAlreadyImportedOrNull(const Decl *FromD) const {
+  auto Pos = ImportedDecls.find(FromD);
+  if (Pos != ImportedDecls.end())
+return Pos->second;
+  else
 return nullptr;
-  }
 }
 
 Expected ASTImporter::Import_New(Decl *FromD) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53699: [ASTImporter] Fix inequality of functions with different attributes

2018-12-17 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

Ping @shafik, I have addressed you comments, could you please take another 
look? If you don't have any objections, could you please approve?


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53699/new/

https://reviews.llvm.org/D53699



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


[PATCH] D55280: [CTU] Make loadExternalAST return with non nullptr on success

2018-12-17 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

Ping @a_sidorin Could you please take another look and consider my previous 
comment?


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55280/new/

https://reviews.llvm.org/D55280



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


[PATCH] D53708: [ASTImporter] Add importer specific lookup

2018-12-17 Thread Gabor Marton via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL349351: [ASTImporter] Add importer specific lookup (authored 
by martong, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53708/new/

https://reviews.llvm.org/D53708

Files:
  cfe/trunk/include/clang/AST/ASTImporter.h
  cfe/trunk/include/clang/AST/ASTImporterLookupTable.h
  cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h
  cfe/trunk/lib/AST/ASTImporter.cpp
  cfe/trunk/lib/AST/ASTImporterLookupTable.cpp
  cfe/trunk/lib/AST/CMakeLists.txt
  cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
  cfe/trunk/lib/Frontend/ASTMerge.cpp
  cfe/trunk/unittests/AST/ASTImporterTest.cpp

Index: cfe/trunk/lib/AST/ASTImporterLookupTable.cpp
===
--- cfe/trunk/lib/AST/ASTImporterLookupTable.cpp
+++ cfe/trunk/lib/AST/ASTImporterLookupTable.cpp
@@ -0,0 +1,129 @@
+//===- ASTImporterLookupTable.cpp - ASTImporter specific lookup ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+//  This file defines the ASTImporterLookupTable class which implements a
+//  lookup procedure for the import mechanism.
+//
+//===--===//
+
+#include "clang/AST/ASTImporterLookupTable.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+
+namespace clang {
+
+namespace {
+
+struct Builder : RecursiveASTVisitor {
+  ASTImporterLookupTable 
+  Builder(ASTImporterLookupTable ) : LT(LT) {}
+  bool VisitNamedDecl(NamedDecl *D) {
+LT.add(D);
+return true;
+  }
+  bool VisitFriendDecl(FriendDecl *D) {
+if (D->getFriendType()) {
+  QualType Ty = D->getFriendType()->getType();
+  // FIXME Can this be other than elaborated?
+  QualType NamedTy = cast(Ty)->getNamedType();
+  if (!NamedTy->isDependentType()) {
+if (const auto *RTy = dyn_cast(NamedTy))
+  LT.add(RTy->getAsCXXRecordDecl());
+else if (const auto *SpecTy =
+ dyn_cast(NamedTy)) {
+  LT.add(SpecTy->getAsCXXRecordDecl());
+}
+  }
+}
+return true;
+  }
+
+  // Override default settings of base.
+  bool shouldVisitTemplateInstantiations() const { return true; }
+  bool shouldVisitImplicitCode() const { return true; }
+};
+
+} // anonymous namespace
+
+ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl ) {
+  Builder B(*this);
+  B.TraverseDecl();
+}
+
+void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
+  DeclList  = LookupTable[DC][ND->getDeclName()];
+  // Inserts if and only if there is no element in the container equal to it.
+  Decls.insert(ND);
+}
+
+void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
+  DeclList  = LookupTable[DC][ND->getDeclName()];
+  bool EraseResult = Decls.remove(ND);
+  (void)EraseResult;
+  assert(EraseResult == true && "Trying to remove not contained Decl");
+}
+
+void ASTImporterLookupTable::add(NamedDecl *ND) {
+  assert(ND);
+  DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
+  add(DC, ND);
+  DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
+  if (DC != ReDC)
+add(ReDC, ND);
+}
+
+void ASTImporterLookupTable::remove(NamedDecl *ND) {
+  assert(ND);
+  DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
+  remove(DC, ND);
+  DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
+  if (DC != ReDC)
+remove(ReDC, ND);
+}
+
+ASTImporterLookupTable::LookupResult
+ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
+  auto DCI = LookupTable.find(DC->getPrimaryContext());
+  if (DCI == LookupTable.end())
+return {};
+
+  const auto  = DCI->second;
+  auto NamesI = FoundNameMap.find(Name);
+  if (NamesI == FoundNameMap.end())
+return {};
+
+  return NamesI->second;
+}
+
+void ASTImporterLookupTable::dump(DeclContext *DC) const {
+  auto DCI = LookupTable.find(DC->getPrimaryContext());
+  if (DCI == LookupTable.end())
+llvm::errs() << "empty\n";
+  const auto  = DCI->second;
+  for (const auto  : FoundNameMap) {
+DeclarationName Name = Entry.first;
+llvm::errs() << " Name: ";
+Name.dump();
+const DeclList& List = Entry.second;
+for (NamedDecl *ND : List) {
+  ND->dump();
+}
+  }
+}
+
+void ASTImporterLookupTable::dump() const {
+  for (const auto  : LookupTable) {
+DeclContext *DC = Entry.first;
+StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
+llvm::errs() << "== DC:" << cast(DC) << Primary << "\n";
+dump(DC);
+  }
+}
+
+} // namespace clang
Index: cfe/trunk/lib/AST/ASTImporter.cpp

[PATCH] D53655: [ASTImporter] Fix redecl chain of classes and class templates

2018-12-17 Thread Gabor Marton via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC349349: [ASTImporter] Fix redecl chain of classes and class 
templates (authored by martong, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D53655?vs=175641=178450#toc

Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53655/new/

https://reviews.llvm.org/D53655

Files:
  docs/LibASTMatchersReference.html
  include/clang/ASTMatchers/ASTMatchers.h
  lib/AST/ASTImporter.cpp
  lib/AST/DeclBase.cpp
  lib/ASTMatchers/ASTMatchersInternal.cpp
  lib/ASTMatchers/Dynamic/Registry.cpp
  unittests/AST/ASTImporterTest.cpp
  unittests/AST/StructuralEquivalenceTest.cpp

Index: docs/LibASTMatchersReference.html
===
--- docs/LibASTMatchersReference.html
+++ docs/LibASTMatchersReference.html
@@ -300,6 +300,16 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DeclindirectFieldDeclMatcherhttps://clang.llvm.org/doxygen/classclang_1_1IndirectFieldDecl.html;>IndirectFieldDecl...
+Matches indirect field declarations.
+
+Given
+  struct X { struct { int a; }; };
+indirectFieldDecl()
+  matches 'a'.
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DecllabelDeclMatcherhttps://clang.llvm.org/doxygen/classclang_1_1LabelDecl.html;>LabelDecl...
 Matches a declaration of label.
 
Index: include/clang/ASTMatchers/ASTMatchers.h
===
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -1158,6 +1158,17 @@
 ///   matches 'm'.
 extern const internal::VariadicDynCastAllOfMatcher fieldDecl;
 
+/// Matches indirect field declarations.
+///
+/// Given
+/// \code
+///   struct X { struct { int a; }; };
+/// \endcode
+/// indirectFieldDecl()
+///   matches 'a'.
+extern const internal::VariadicDynCastAllOfMatcher
+indirectFieldDecl;
+
 /// Matches function declarations.
 ///
 /// Example matches f
Index: lib/AST/DeclBase.cpp
===
--- lib/AST/DeclBase.cpp
+++ lib/AST/DeclBase.cpp
@@ -1463,7 +1463,9 @@
   if (Map) {
 StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
 assert(Pos != Map->end() && "no lookup entry for decl");
-if (Pos->second.getAsVector() || Pos->second.getAsDecl() == ND)
+// Remove the decl only if it is contained.
+StoredDeclsList::DeclsTy *Vec = Pos->second.getAsVector();
+if ((Vec && is_contained(*Vec, ND)) || Pos->second.getAsDecl() == ND)
   Pos->second.remove(ND);
   }
 } while (DC->isTransparentContext() && (DC = DC->getParent()));
Index: lib/AST/ASTImporter.cpp
===
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -122,6 +122,8 @@
   return getCanonicalForwardRedeclChain(FD);
 if (auto *VD = dyn_cast(D))
   return getCanonicalForwardRedeclChain(VD);
+if (auto *TD = dyn_cast(D))
+  return getCanonicalForwardRedeclChain(TD);
 llvm_unreachable("Bad declaration kind");
   }
 
@@ -2607,10 +2609,9 @@
   return std::move(Err);
 IDNS = Decl::IDNS_Ordinary;
   } else if (Importer.getToContext().getLangOpts().CPlusPlus)
-IDNS |= Decl::IDNS_Ordinary;
+IDNS |= Decl::IDNS_Ordinary | Decl::IDNS_TagFriend;
 
   // We may already have a record of the same name; try to find and match it.
-  RecordDecl *AdoptDecl = nullptr;
   RecordDecl *PrevDecl = nullptr;
   if (!DC->isFunctionOrMethod()) {
 SmallVector ConflictingDecls;
@@ -2643,26 +2644,22 @@
   }
 
   if (auto *FoundRecord = dyn_cast(Found)) {
-if (!SearchName) {
+// Do not emit false positive diagnostic in case of unnamed
+// struct/union and in case of anonymous structs.  Would be false
+// because there may be several anonymous/unnamed structs in a class.
+// E.g. these are both valid:
+//  struct A { // unnamed structs
+//struct { struct A *next; } entry0;
+//struct { struct A *next; } entry1;
+//  };
+//  struct X { struct { int a; }; struct { int b; }; }; // anon structs
+if (!SearchName)
   if (!IsStructuralMatch(D, FoundRecord, false))
 continue;
-} else {
-  if (!IsStructuralMatch(D, FoundRecord)) {
-ConflictingDecls.push_back(FoundDecl);
-continue;
-  }
-}
 
-PrevDecl = FoundRecord;
-
-if (RecordDecl *FoundDef = FoundRecord->getDefinition()) {
-  if ((SearchName && !D->isCompleteDefinition() && !IsFriendTemplate)
-  || (D->isCompleteDefinition() &&
-  D->isAnonymousStructOrUnion()
-== FoundDef->isAnonymousStructOrUnion())) {
-// The record types structurally match, or the "from" translation
-// unit only 

[PATCH] D53708: [ASTImporter] Add importer specific lookup

2018-12-17 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 178452.
martong added a comment.

- Rebase to master (trunk)


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53708/new/

https://reviews.llvm.org/D53708

Files:
  include/clang/AST/ASTImporter.h
  include/clang/AST/ASTImporterLookupTable.h
  include/clang/CrossTU/CrossTranslationUnit.h
  lib/AST/ASTImporter.cpp
  lib/AST/ASTImporterLookupTable.cpp
  lib/AST/CMakeLists.txt
  lib/CrossTU/CrossTranslationUnit.cpp
  lib/Frontend/ASTMerge.cpp
  unittests/AST/ASTImporterTest.cpp

Index: unittests/AST/ASTImporterTest.cpp
===
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -15,6 +15,8 @@
 #include "MatchVerifier.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclContextInternals.h"
+#include "clang/AST/ASTImporter.h"
+#include "clang/AST/ASTImporterLookupTable.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/Tooling.h"
@@ -308,24 +310,27 @@
   Unit->enableSourceFileDiagnostics();
 }
 
-void lazyInitImporter(ASTUnit *ToAST) {
+void lazyInitImporter(ASTImporterLookupTable , ASTUnit *ToAST) {
   assert(ToAST);
   if (!Importer) {
-Importer.reset(new ASTImporter(
-ToAST->getASTContext(), ToAST->getFileManager(),
-Unit->getASTContext(), Unit->getFileManager(), false));
+Importer.reset(
+new ASTImporter(ToAST->getASTContext(), ToAST->getFileManager(),
+Unit->getASTContext(), Unit->getFileManager(),
+false, ));
   }
   assert(>getASTContext() == >getToContext());
   createVirtualFileIfNeeded(ToAST, FileName, Code);
 }
 
-Decl *import(ASTUnit *ToAST, Decl *FromDecl) {
-  lazyInitImporter(ToAST);
+Decl *import(ASTImporterLookupTable , ASTUnit *ToAST,
+ Decl *FromDecl) {
+  lazyInitImporter(LookupTable, ToAST);
   return Importer->Import(FromDecl);
- }
+}
 
-QualType import(ASTUnit *ToAST, QualType FromType) {
-  lazyInitImporter(ToAST);
+QualType import(ASTImporterLookupTable , ASTUnit *ToAST,
+QualType FromType) {
+  lazyInitImporter(LookupTable, ToAST);
   return Importer->Import(FromType);
 }
   };
@@ -339,13 +344,23 @@
   // vector is expanding, with the list we won't have these issues.
   std::list FromTUs;
 
-  void lazyInitToAST(Language ToLang) {
+  // Initialize the lookup table if not initialized already.
+  void lazyInitLookupTable(TranslationUnitDecl *ToTU) {
+assert(ToTU);
+if (!LookupTablePtr)
+  LookupTablePtr = llvm::make_unique(*ToTU);
+  }
+
+  void lazyInitToAST(Language ToLang, StringRef ToSrcCode, StringRef FileName) {
 if (ToAST)
   return;
 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
+// Source code must be a valid live buffer through the tests lifetime.
+ToCode = ToSrcCode;
 // Build the AST from an empty file.
-ToAST = tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
+ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, FileName);
 ToAST->enableSourceFileDiagnostics();
+lazyInitLookupTable(ToAST->getASTContext().getTranslationUnitDecl());
   }
 
   TU *findFromTU(Decl *From) {
@@ -359,6 +374,10 @@
 return &*It;
   }
 
+protected:
+
+  std::unique_ptr LookupTablePtr;
+
 public:
   // We may have several From context but only one To context.
   std::unique_ptr ToAST;
@@ -375,26 +394,23 @@
 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
 TU  = FromTUs.back();
 
-ToCode = ToSrcCode;
 assert(!ToAST);
-ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
-ToAST->enableSourceFileDiagnostics();
+lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
 
 ASTContext  = FromTU.Unit->getASTContext();
 
-createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
-
 IdentifierInfo *ImportedII = (Identifier);
 assert(ImportedII && "Declaration with the given identifier "
  "should be specified in test!");
 DeclarationName ImportDeclName(ImportedII);
-SmallVector FoundDecls;
+SmallVector FoundDecls;
 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
   FoundDecls);
 
 assert(FoundDecls.size() == 1);
 
-Decl *Imported = FromTU.import(ToAST.get(), FoundDecls.front());
+Decl *Imported =
+FromTU.import(*LookupTablePtr, ToAST.get(), FoundDecls.front());
 
 assert(Imported);
 return std::make_tuple(*FoundDecls.begin(), Imported);
@@ -420,11 +436,8 @@
   // Creates the To context with the given source code and returns the TU decl.
   TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
 ArgVector ToArgs = 

[PATCH] D53708: [ASTImporter] Add importer specific lookup

2018-12-17 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

> This is a perhaps a naive comment, but why is localUncachedLookup used

instead of noload_lookup ? There is a fixme dating from 2013 stating
that noload_lookup should be used instead.

This is not a naive question. I was wondering myself on the very same thing 
when I started working on the ASTImporter at 2017. 
I think when `noload_lookup` was introduced the author of that function tried 
to replace `localUncachedLookup` in ASTImporter, but that broke some tests. The 
major difference between the two functions is that the latter can find 
declarations even if they are not stored in the `LookupPtr`. This is rather 
unusual from the C/C++ point of view of lookup, and not working in all cases 
(see the introduction of this patch). Ironically, I can't just get rid of 
`localUncachedLookup` because it would break some LLDB test cases.


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53708/new/

https://reviews.llvm.org/D53708



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


[PATCH] D44100: [ASTImporter] Reorder fields after structure import is finished

2018-12-17 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

Alexey, simply put, the crux of the problem is this:
The imported decl context is different than what we get by calling the 
`getDeclContext()` on an imported field/friend of the "from" decl context.

With other words:
`import(cast(FromDC)` gives us a different value than what we get from 
`ToD->getDeclContext()` inside the for loop which iterates over the 
fields/friends of `FromDC`.

This seems abnormal, because we would expect the two to be equal. This is why I 
suspect something related to an LLDB specific use case (and what's worse it 
happens only on macOS). In LLDB, I have seen they first do a minimal import 
then they require the definition with `ASTImporter::importDefinition` (but I am 
not sure if this is the real root cause here). I guess this is a scenario we 
don't have any unittest neither lit tests for in Clang. In an ideal world we 
should fix this inequivalence first and then could we apply this patch.

The workaround I provided is to use the  decl context of the first imported 
field and use that as target decl context (and not use the decl context given 
by import(FromDC)).

Hope this helps


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D44100/new/

https://reviews.llvm.org/D44100



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


[PATCH] D53708: [ASTImporter] Add importer specific lookup

2018-12-17 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

In D53708#1332922 , @riccibruno wrote:

> In D53708#1332868 , @martong wrote:
>
> > > This is a perhaps a naive comment, but why is localUncachedLookup used
> > >  instead of noload_lookup ? There is a fixme dating from 2013 stating
> > >  that noload_lookup should be used instead.
> >
> > This is not a naive question. I was wondering myself on the very same thing 
> > when I started working on the ASTImporter at 2017. 
> >  I think when `noload_lookup` was introduced the author of that function 
> > tried to replace `localUncachedLookup` in ASTImporter, but that broke some 
> > tests. The major difference between the two functions is that the latter 
> > can find declarations even if they are not stored in the `LookupPtr`. This 
> > is rather unusual from the C/C++ point of view of lookup, and not working 
> > in all cases (see the introduction of this patch). Ironically, I can't just 
> > get rid of `localUncachedLookup` because it would break some LLDB test 
> > cases.
>
>
> Ah I think I understand. For my understanding (and please correct me if I am 
> wrong here):
>
> `localUncachedLookup` will first try to do a normal lookup, and if that fails 
> it will try to look in the declarations in the declaration context.
>  Now some declarations (including declarations which are not `NamedDecl` and 
> declarations which matches `shouldBeHidden`)
>  will not be added to the `LookupPtr` (via 
> `makeDeclVisibleInContextWithFlags`) and so will not be found though the 
> normal lookup mechanism. You therefore need to use `localUncachedLookup` to 
> find these.
>
> Does this make sense ?


Exactly. And this seems to be an important feature in ASTImporter, because this 
makes it possible that we can chain into the redecl chain a newly imported AST 
node to existing and structurally equivalent nodes. (The existing nodes are 
found by the lookup and then we iterate over the lookup results searching for 
structurally equivalent ones.)


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53708/new/

https://reviews.llvm.org/D53708



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


[PATCH] D46421: [analyzer][CrossTU] Extend CTU to VarDecls with initializer

2018-12-14 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

Hi Rafael,

This is a great patch and good improvement, thank you! I had a few minor 
comments.
(Also, I was thinking about what else could we import in the future, maybe 
definitions of C++11 enum classes would be also worth to be handled by CTU.)




Comment at: include/clang/CrossTU/CrossTranslationUnit.h:114
+  llvm::Expected
+  getCrossTUDefinition(const VarDecl *VD, StringRef CrossTUDir,
+   StringRef IndexName);

r.stahl wrote:
> xazax.hun wrote:
> > I wonder if we need these overloads. Maybe having only the templated 
> > version and having a static assert for the supported types is better? 
> > Asking the other reviewers as well.
> They are not required, but I thought they make the interface more clear and 
> help prevent implementation in headers.
I consider the new overload just great. Later, if we want we still can extend 
the interface with a template which would call the overloaded functions.



Comment at: lib/CrossTU/CrossTranslationUnit.cpp:117
+}
+static bool hasDefinition(const VarDecl *D, const VarDecl *) {
+  return D->getAnyInitializer(DefD) != nullptr;

The naming here is confusing for me, would be better to be `hasInit`, because 
there are cases when a VarDecl has an initializer but it is not a definition:
```
  struct A {
static const int a = 1 + 2; // VarDecl: has init, but not a definition
  };
  const int A::a; // VarDecl: definition
```
In the above case we probably want to import the initializer and we don't care 
about the definition.



Comment at: lib/CrossTU/CrossTranslationUnit.cpp:120
+}
+template  static bool hasDefinition(const T *D) {
+  const T *Unused;

`hasDefinitionOrInit` ?



Comment at: test/Analysis/Inputs/ctu-other.cpp:79
+};
+extern const S extS = {.a = 4};

Could we have another test case when `S::a` is static?



Comment at: test/Analysis/func-mapping-test.cpp:18
+struct S {
+  int a;
+};

Could we have one more test when we have a `static` member variable?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D46421/new/

https://reviews.llvm.org/D46421



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


[PATCH] D55132: [CTU] Add asserts to protect invariants

2018-11-30 Thread Gabor Marton via Phabricator via cfe-commits
martong created this revision.
martong added reviewers: xazax.hun, a_sidorin.
Herald added subscribers: cfe-commits, gamesh411, Szelethus, dkrupp, rnkovacs.

Repository:
  rC Clang

https://reviews.llvm.org/D55132

Files:
  lib/CrossTU/CrossTranslationUnit.cpp


Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -150,6 +150,7 @@
 CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
   StringRef CrossTUDir,
   StringRef IndexName) {
+  assert(FD && "FD is missing, bad call to this function!");
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
@@ -245,6 +246,8 @@
 
 llvm::Expected
 CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD) {
+  assert(FD->hasBody() && "Functions to be imported should have body.");
+
   ASTImporter  = getOrCreateASTImporter(FD->getASTContext());
   auto *ToDecl =
   cast(Importer.Import(const_cast(FD)));


Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -150,6 +150,7 @@
 CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
   StringRef CrossTUDir,
   StringRef IndexName) {
+  assert(FD && "FD is missing, bad call to this function!");
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
@@ -245,6 +246,8 @@
 
 llvm::Expected
 CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD) {
+  assert(FD->hasBody() && "Functions to be imported should have body.");
+
   ASTImporter  = getOrCreateASTImporter(FD->getASTContext());
   auto *ToDecl =
   cast(Importer.Import(const_cast(FD)));
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55134: [CTU] Add triple/lang mismatch handling

2018-11-30 Thread Gabor Marton via Phabricator via cfe-commits
martong created this revision.
martong added reviewers: xazax.hun, a_sidorin.
Herald added subscribers: cfe-commits, gamesh411, Szelethus, dkrupp, rnkovacs.

We introduce a strict policy for C++ CTU. It can work across TUs only if
the C++ dialects are the same. We neither allow C vs C++ CTU.  We do this
because the same constructs might be represented with different properties in
the corresponding AST nodes or even the nodes might be completely different (a
struct will be RecordDecl in C, but it will be a CXXRectordDecl in C++, thus it
may cause certain assertions during cast operations).


Repository:
  rC Clang

https://reviews.llvm.org/D55134

Files:
  include/clang/Basic/DiagnosticCrossTUKinds.td
  include/clang/CrossTU/CrossTranslationUnit.h
  lib/CrossTU/CrossTranslationUnit.cpp

Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -28,6 +28,36 @@
 #include 
 #include 
 
+namespace llvm {
+// Same as Triple's equality operator, but we check a field only if that is
+// known in both instances.
+bool hasEqualKnownFields(const Triple , const Triple ) {
+  return ((Lhs.getArch() != Triple::UnknownArch &&
+   Rhs.getArch() != Triple::UnknownArch)
+  ? Lhs.getArch() == Rhs.getArch()
+  : true) &&
+ ((Lhs.getSubArch() != Triple::NoSubArch &&
+   Rhs.getSubArch() != Triple::NoSubArch)
+  ? Lhs.getSubArch() == Rhs.getSubArch()
+  : true) &&
+ ((Lhs.getVendor() != Triple::UnknownVendor &&
+   Rhs.getVendor() != Triple::UnknownVendor)
+  ? Lhs.getVendor() == Rhs.getVendor()
+  : true) &&
+ ((Lhs.getOS() != Triple::UnknownOS && Rhs.getOS() != Triple::UnknownOS)
+  ? Lhs.getOS() == Rhs.getOS()
+  : true) &&
+ ((Lhs.getEnvironment() != Triple::UnknownEnvironment &&
+   Rhs.getEnvironment() != Triple::UnknownEnvironment)
+  ? Lhs.getEnvironment() == Rhs.getEnvironment()
+  : true) &&
+ ((Lhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+   Rhs.getObjectFormat() != Triple::UnknownObjectFormat)
+  ? Lhs.getObjectFormat() == Rhs.getObjectFormat()
+  : true);
+}
+}
+
 namespace clang {
 namespace cross_tu {
 
@@ -55,6 +85,10 @@
   return "Failed to load external AST source.";
 case index_error_code::failed_to_generate_usr:
   return "Failed to generate USR.";
+case index_error_code::triple_mismatch:
+  return "Triple mismatch";
+case index_error_code::lang_mismatch:
+  return "Language mismatch";
 }
 llvm_unreachable("Unrecognized index_error_code.");
   }
@@ -166,6 +200,30 @@
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
+  const auto& TripleTo = Context.getTargetInfo().getTriple();
+  const auto& TripleFrom = Unit->getASTContext().getTargetInfo().getTriple();
+  // The imported AST had been generated for a different target.
+  // Some parts of the triple in the loaded ASTContext can be unknown while the
+  // very same parts in the target ASTContext are known. Thus we check for the
+  // known parts only.
+  if (!hasEqualKnownFields(TripleTo, TripleFrom)) {
+// TODO pass the SourceLocation of the CallExpression for more precise
+// diagnostics
+Context.getDiagnostics().Report(diag::err_ctu_incompat_triple)
+<< Unit->getMainFileName() << TripleTo.str() << TripleFrom.str();
+// TODO Add statistics here
+return llvm::make_error(index_error_code::triple_mismatch);
+  }
+
+  const auto& LangTo = Context.getLangOpts();
+  const auto& LangFrom = Unit->getASTContext().getLangOpts();
+  // FIXME: Currenty we do not support CTU across C++ and C and across
+  // different dialects of C++.
+  if (LangTo.CPlusPlus != LangFrom.CPlusPlus) {
+// TODO Add statistics here.
+return llvm::make_error(index_error_code::lang_mismatch);
+  }
+
   TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
   if (const FunctionDecl *ResultDecl =
   findFunctionInDeclContext(TU, LookupFnName))
Index: include/clang/CrossTU/CrossTranslationUnit.h
===
--- include/clang/CrossTU/CrossTranslationUnit.h
+++ include/clang/CrossTU/CrossTranslationUnit.h
@@ -41,7 +41,9 @@
   missing_definition,
   failed_import,
   failed_to_get_external_ast,
-  failed_to_generate_usr
+  failed_to_generate_usr,
+  triple_mismatch,
+  lang_mismatch
 };
 
 class IndexError : public llvm::ErrorInfo {
Index: include/clang/Basic/DiagnosticCrossTUKinds.td
===
--- include/clang/Basic/DiagnosticCrossTUKinds.td
+++ include/clang/Basic/DiagnosticCrossTUKinds.td
@@ -15,4 +15,7 @@
 
 def err_multiple_def_index : Error<
   "multiple definitions 

[PATCH] D55129: [CTU] Eliminate race condition in CTU lit tests

2018-11-30 Thread Gabor Marton via Phabricator via cfe-commits
martong created this revision.
martong added reviewers: xazax.hun, a_sidorin.
Herald added subscribers: cfe-commits, gamesh411, Szelethus, dkrupp, rnkovacs.

We plan to introduce additional CTU related lit test. Since lit may run the
tests in parallel, it is not safe to use the same directory (%T) for these
tests. It is safe to use however test case specific directories (%t).


Repository:
  rC Clang

https://reviews.llvm.org/D55129

Files:
  test/Analysis/ctu-main.cpp


Index: test/Analysis/ctu-main.cpp
===
--- test/Analysis/ctu-main.cpp
+++ test/Analysis/ctu-main.cpp
@@ -1,8 +1,8 @@
-// RUN: mkdir -p %T/ctudir
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o 
%T/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o 
%T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
-// RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze 
-analyzer-checker=core,debug.ExprInspection -analyzer-config 
experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir 
-verify %s
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o 
%t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o 
%t/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze 
-analyzer-checker=core,debug.ExprInspection -analyzer-config 
experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%t/ctudir 
-verify %s
 
 #include "ctu-hdr.h"
 


Index: test/Analysis/ctu-main.cpp
===
--- test/Analysis/ctu-main.cpp
+++ test/Analysis/ctu-main.cpp
@@ -1,8 +1,8 @@
-// RUN: mkdir -p %T/ctudir
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
-// RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %t/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%t/ctudir -verify %s
 
 #include "ctu-hdr.h"
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55131: [CTU] Add more lit tests and better error handling

2018-11-30 Thread Gabor Marton via Phabricator via cfe-commits
martong created this revision.
martong added reviewers: xazax.hun, balazske, a_sidorin.
Herald added subscribers: cfe-commits, gamesh411, Szelethus, dkrupp, rnkovacs.

Adding some more CTU list tests. E.g. to check if a construct is unsupported.
We also slightly modify the handling of the return value of the `Import`
function from ASTImporter.


Repository:
  rC Clang

https://reviews.llvm.org/D55131

Files:
  lib/CrossTU/CrossTranslationUnit.cpp
  test/Analysis/Inputs/ctu-other.c
  test/Analysis/Inputs/externalFnMap2.txt
  test/Analysis/ctu-main.c

Index: test/Analysis/ctu-main.c
===
--- /dev/null
+++ test/Analysis/ctu-main.c
@@ -0,0 +1,60 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir2
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %t/ctudir2/ctu-other.c.ast %S/Inputs/ctu-other.c
+// RUN: cp %S/Inputs/externalFnMap2.txt %t/ctudir2/externalFnMap.txt
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -std=c89 -analyze -analyzer-checker=core,debug.ExprInspection  -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%t/ctudir2 -verify %s
+
+void clang_analyzer_eval(int);
+
+typedef struct {
+  int a;
+  int b;
+} foobar;
+
+static int s1 = 21;
+
+int f(int);
+int enumcheck(void);
+int static_check(void);
+
+enum A { x,
+ y,
+ z };
+
+extern foobar fb;
+
+int getkey();
+
+int main() {
+  clang_analyzer_eval(f(5) == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(x == 0);// expected-warning{{TRUE}}
+  clang_analyzer_eval(enumcheck() == 42); // expected-warning{{TRUE}}
+
+  return getkey();
+}
+
+// Test reporting error in a macro.
+struct S;
+int g(struct S *);
+void test_macro(void) {
+  g(0); // expected-warning@Inputs/ctu-other.c:31 {{Access to field 'a' results in a dereference of a null pointer (loaded from variable 'ctx')}}
+}
+
+// The external function prototype is incomplete.
+// warning:implicit functions are prohibited by c99
+void test_implicit(){
+int res=ident_implicit(6);// external implicit functions are not inlined
+clang_analyzer_eval(res == 6); // expected-warning{{TRUE}}
+}
+
+
+// Tests the import of functions that have a struct parameter
+// defined in its prototype.
+struct data_t{int a;int b;};
+int struct_in_proto(struct data_t *d);
+void test_struct_def_in_argument(){
+  struct data_t d;
+  d.a=1;
+  d.b=0;
+  clang_analyzer_eval(struct_in_proto()==0);// expected-warning{{UNKNOWN}}
+}
Index: test/Analysis/Inputs/externalFnMap2.txt
===
--- /dev/null
+++ test/Analysis/Inputs/externalFnMap2.txt
@@ -0,0 +1,6 @@
+c:@F@getkey ctu-other.c.ast
+c:@F@g ctu-other.c.ast
+c:@F@f ctu-other.c.ast
+c:@F@enumcheck ctu-other.c.ast
+c:@F@ident_implicit ctu-other.c.ast
+c:@F@struct_in_proto ctu-other.c.ast
Index: test/Analysis/Inputs/ctu-other.c
===
--- /dev/null
+++ test/Analysis/Inputs/ctu-other.c
@@ -0,0 +1,51 @@
+enum B {x = 42,l,s};
+
+typedef struct {
+  int a;
+  int b;
+} foobar;
+
+int enumcheck(void) {
+  return x;
+}
+
+foobar fb;
+
+int f(int i) {
+  if (fb.a) {
+fb.b = i;
+  }
+  return 1;
+}
+
+//TEST reporting an
+//error in macro
+//definition
+#define MYMACRO(ctx) \
+ctx->a;
+struct S{
+  int a;
+};
+
+int g(struct S *ctx){
+  MYMACRO(ctx);
+  return 0;
+}
+
+// TEST asm import not failing
+int getkey() {
+  int res;
+  asm ( "mov $42, %0"
+  : "=r" (res));
+  return res;
+}
+
+//Implicit function
+int ident_implicit(int in){
+return in;
+}
+
+//ASTImporter doesn't support this
+int struct_in_proto(struct data_t{int a;int b;} *d){
+  return 0;
+}
Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -247,7 +247,10 @@
 CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD) {
   ASTImporter  = getOrCreateASTImporter(FD->getASTContext());
   auto *ToDecl =
-  cast(Importer.Import(const_cast(FD)));
+  cast_or_null(Importer.Import(const_cast(FD)));
+  if (!ToDecl) {
+return llvm::make_error(index_error_code::failed_import);
+  }
   assert(ToDecl->hasBody());
   assert(FD->hasBody() && "Functions already imported should have body.");
   return ToDecl;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55133: [CTU] Add statistics

2018-11-30 Thread Gabor Marton via Phabricator via cfe-commits
martong created this revision.
martong added reviewers: xazax.hun, a_sidorin.
Herald added subscribers: cfe-commits, gamesh411, Szelethus, dkrupp, rnkovacs.

Repository:
  rC Clang

https://reviews.llvm.org/D55133

Files:
  lib/CrossTU/CrossTranslationUnit.cpp


Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -21,6 +21,7 @@
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Index/USRGeneration.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Statistic.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/Path.h"
@@ -32,6 +33,15 @@
 namespace cross_tu {
 
 namespace {
+#define DEBUG_TYPE "CrossTranslationUnit"
+STATISTIC(NumGetCTUCalled, "The # of getCTUDefinition function called");
+STATISTIC(NumNoUnit, "The # of getCTUDefinition NoUnit");
+STATISTIC(
+NumNotInOtherTU,
+"The # of getCTUDefinition called but the function is not in other TU");
+STATISTIC(NumGetCTUSuccess, "The # of getCTUDefinition successfully return the 
"
+"requested function's body");
+
 // FIXME: This class is will be removed after the transition to llvm::Error.
 class IndexErrorCategory : public std::error_category {
 public:
@@ -151,18 +161,23 @@
   StringRef CrossTUDir,
   StringRef IndexName) {
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
+  ++NumGetCTUCalled;
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
 return llvm::make_error(
 index_error_code::failed_to_generate_usr);
   llvm::Expected ASTUnitOrError =
   loadExternalAST(LookupFnName, CrossTUDir, IndexName);
-  if (!ASTUnitOrError)
+  if (!ASTUnitOrError) {
+++NumNoUnit;
 return ASTUnitOrError.takeError();
+  }
   ASTUnit *Unit = *ASTUnitOrError;
-  if (!Unit)
+  if (!Unit) {
+++NumNoUnit;
 return llvm::make_error(
 index_error_code::failed_to_get_external_ast);
+  }
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
@@ -216,8 +231,10 @@
 }
 
 auto It = FunctionFileMap.find(LookupName);
-if (It == FunctionFileMap.end())
+if (It == FunctionFileMap.end()) {
+  ++NumNotInOtherTU;
   return 
llvm::make_error(index_error_code::missing_definition);
+}
 StringRef ASTFileName = It->second;
 auto ASTCacheEntry = FileASTUnitMap.find(ASTFileName);
 if (ASTCacheEntry == FileASTUnitMap.end()) {
@@ -250,6 +267,7 @@
   cast(Importer.Import(const_cast(FD)));
   assert(ToDecl->hasBody());
   assert(FD->hasBody() && "Functions already imported should have body.");
+  ++NumGetCTUSuccess;
   return ToDecl;
 }
 


Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -21,6 +21,7 @@
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Index/USRGeneration.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Statistic.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/Path.h"
@@ -32,6 +33,15 @@
 namespace cross_tu {
 
 namespace {
+#define DEBUG_TYPE "CrossTranslationUnit"
+STATISTIC(NumGetCTUCalled, "The # of getCTUDefinition function called");
+STATISTIC(NumNoUnit, "The # of getCTUDefinition NoUnit");
+STATISTIC(
+NumNotInOtherTU,
+"The # of getCTUDefinition called but the function is not in other TU");
+STATISTIC(NumGetCTUSuccess, "The # of getCTUDefinition successfully return the "
+"requested function's body");
+
 // FIXME: This class is will be removed after the transition to llvm::Error.
 class IndexErrorCategory : public std::error_category {
 public:
@@ -151,18 +161,23 @@
   StringRef CrossTUDir,
   StringRef IndexName) {
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
+  ++NumGetCTUCalled;
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
 return llvm::make_error(
 index_error_code::failed_to_generate_usr);
   llvm::Expected ASTUnitOrError =
   loadExternalAST(LookupFnName, CrossTUDir, IndexName);
-  if (!ASTUnitOrError)
+  if (!ASTUnitOrError) {
+++NumNoUnit;
 return ASTUnitOrError.takeError();
+  }
   ASTUnit *Unit = *ASTUnitOrError;
-  if (!Unit)
+  if (!Unit) {
+++NumNoUnit;
 return llvm::make_error(
 index_error_code::failed_to_get_external_ast);
+  }
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
@@ -216,8 +231,10 @@
 }
 
 auto 

[PATCH] D55135: [CTU][Analyzer]Add DisplayCTUProgress analyzer switch

2018-11-30 Thread Gabor Marton via Phabricator via cfe-commits
martong created this revision.
martong added reviewers: xazax.hun, Szelethus, a_sidorin.
Herald added subscribers: cfe-commits, gamesh411, dkrupp, donat.nagy, 
mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, whisperity.
Herald added a reviewer: george.karpenkov.

With a new switch we may be able to print to stderr if a new TU is being loaded
during CTU.  This is very important for higher level scripts (like CodeChecker)
to be able to parse this output so they can create e.g. a zip file in case of
a Clang crash which contains all the related TU files.


Repository:
  rC Clang

https://reviews.llvm.org/D55135

Files:
  include/clang/CrossTU/CrossTranslationUnit.h
  include/clang/Driver/CC1Options.td
  include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
  lib/CrossTU/CrossTranslationUnit.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/StaticAnalyzer/Core/CallEvent.cpp
  test/Analysis/ctu-main.cpp

Index: test/Analysis/ctu-main.cpp
===
--- test/Analysis/ctu-main.cpp
+++ test/Analysis/ctu-main.cpp
@@ -3,6 +3,10 @@
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
 // RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -analyzer-display-ctu-progress 2>&1 %s | FileCheck %s
+
+// CHECK: ANALYZE (CTU loaded AST for source file): {{.*}}/ctu-other.cpp
+// CHECK: ANALYZE (CTU loaded AST for source file): {{.*}}/ctu-chain.cpp
 
 #include "ctu-hdr.h"
 
Index: lib/StaticAnalyzer/Core/CallEvent.cpp
===
--- lib/StaticAnalyzer/Core/CallEvent.cpp
+++ lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -560,7 +560,8 @@
   cross_tu::CrossTranslationUnitContext  =
   *Engine->getCrossTranslationUnitContext();
   llvm::Expected CTUDeclOrError =
-  CTUCtx.getCrossTUDefinition(FD, Opts.getCTUDir(), Opts.getCTUIndexName());
+  CTUCtx.getCrossTUDefinition(FD, Opts.getCTUDir(), Opts.getCTUIndexName(),
+  Opts.AnalyzerDisplayCtuProgress);
 
   if (!CTUDeclOrError) {
 handleAllErrors(CTUDeclOrError.takeError(),
Index: lib/Frontend/CompilerInvocation.cpp
===
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -289,6 +289,8 @@
   Opts.NoRetryExhausted = Args.hasArg(OPT_analyzer_disable_retry_exhausted);
   Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers);
   Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress);
+  Opts.AnalyzerDisplayCtuProgress =
+  Args.hasArg(OPT_analyzer_display_ctu_progress);
   Opts.AnalyzeNestedBlocks =
 Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks);
   Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function);
Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -149,14 +149,15 @@
 llvm::Expected
 CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
   StringRef CrossTUDir,
-  StringRef IndexName) {
+  StringRef IndexName,
+  bool DisplayCTUProgress) {
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
 return llvm::make_error(
 index_error_code::failed_to_generate_usr);
   llvm::Expected ASTUnitOrError =
-  loadExternalAST(LookupFnName, CrossTUDir, IndexName);
+  loadExternalAST(LookupFnName, CrossTUDir, IndexName, DisplayCTUProgress);
   if (!ASTUnitOrError)
 return ASTUnitOrError.takeError();
   ASTUnit *Unit = *ASTUnitOrError;
@@ -193,7 +194,8 @@
 }
 
 llvm::Expected CrossTranslationUnitContext::loadExternalAST(
-StringRef LookupName, StringRef CrossTUDir, StringRef IndexName) {
+StringRef LookupName, StringRef CrossTUDir, StringRef IndexName,
+bool DisplayCTUProgress) {
   // FIXME: The current implementation only supports loading functions with
   //a lookup name from a single translation unit. If multiple
   //translation units contains functions with the same lookup name an
@@ -233,6 +235,10 @@
   ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts()));
   

[PATCH] D53655: [ASTImporter] Fix redecl chain of classes and class templates

2018-11-28 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 175641.
martong marked 2 inline comments as done.
martong added a comment.

- Remove containsInVector


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53655/new/

https://reviews.llvm.org/D53655

Files:
  docs/LibASTMatchersReference.html
  include/clang/ASTMatchers/ASTMatchers.h
  lib/AST/ASTImporter.cpp
  lib/AST/DeclBase.cpp
  lib/ASTMatchers/ASTMatchersInternal.cpp
  lib/ASTMatchers/Dynamic/Registry.cpp
  unittests/AST/ASTImporterTest.cpp
  unittests/AST/StructuralEquivalenceTest.cpp

Index: unittests/AST/StructuralEquivalenceTest.cpp
===
--- unittests/AST/StructuralEquivalenceTest.cpp
+++ unittests/AST/StructuralEquivalenceTest.cpp
@@ -597,6 +597,77 @@
   EXPECT_FALSE(testStructuralMatch(R0, R1));
 }
 
+TEST_F(StructuralEquivalenceRecordTest, AnonymousRecordsShouldBeInequivalent) {
+  auto t = makeTuDecls(
+  R"(
+  struct X {
+struct {
+  int a;
+};
+struct {
+  int b;
+};
+  };
+  )",
+  "", Lang_C);
+  auto *TU = get<0>(t);
+  auto *A = FirstDeclMatcher().match(
+  TU, indirectFieldDecl(hasName("a")));
+  auto *FA = cast(A->chain().front());
+  RecordDecl *RA = cast(FA->getType().getTypePtr())->getDecl();
+  auto *B = FirstDeclMatcher().match(
+  TU, indirectFieldDecl(hasName("b")));
+  auto *FB = cast(B->chain().front());
+  RecordDecl *RB = cast(FB->getType().getTypePtr())->getDecl();
+
+  ASSERT_NE(RA, RB);
+  EXPECT_TRUE(testStructuralMatch(RA, RA));
+  EXPECT_TRUE(testStructuralMatch(RB, RB));
+  EXPECT_FALSE(testStructuralMatch(RA, RB));
+}
+
+TEST_F(StructuralEquivalenceRecordTest,
+   RecordsAreInequivalentIfOrderOfAnonRecordsIsDifferent) {
+  auto t = makeTuDecls(
+  R"(
+  struct X {
+struct { int a; };
+struct { int b; };
+  };
+  )",
+  R"(
+  struct X { // The order is reversed.
+struct { int b; };
+struct { int a; };
+  };
+  )",
+  Lang_C);
+
+  auto *TU = get<0>(t);
+  auto *A = FirstDeclMatcher().match(
+  TU, indirectFieldDecl(hasName("a")));
+  auto *FA = cast(A->chain().front());
+  RecordDecl *RA = cast(FA->getType().getTypePtr())->getDecl();
+
+  auto *TU1 = get<1>(t);
+  auto *A1 = FirstDeclMatcher().match(
+  TU1, indirectFieldDecl(hasName("a")));
+  auto *FA1 = cast(A1->chain().front());
+  RecordDecl *RA1 = cast(FA1->getType().getTypePtr())->getDecl();
+
+  RecordDecl *X =
+  FirstDeclMatcher().match(TU, recordDecl(hasName("X")));
+  RecordDecl *X1 =
+  FirstDeclMatcher().match(TU1, recordDecl(hasName("X")));
+  ASSERT_NE(X, X1);
+  EXPECT_FALSE(testStructuralMatch(X, X1));
+
+  ASSERT_NE(RA, RA1);
+  EXPECT_TRUE(testStructuralMatch(RA, RA));
+  EXPECT_TRUE(testStructuralMatch(RA1, RA1));
+  EXPECT_FALSE(testStructuralMatch(RA1, RA));
+}
+
 TEST_F(StructuralEquivalenceRecordTest,
UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) {
   auto Code =
Index: unittests/AST/ASTImporterTest.cpp
===
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -11,9 +11,10 @@
 //
 //===--===//
 
+#include "clang/AST/ASTImporter.h"
 #include "MatchVerifier.h"
 #include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTImporter.h"
+#include "clang/AST/DeclContextInternals.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/Tooling.h"
@@ -1808,6 +1809,65 @@
   EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
 }
 
+TEST_P(ASTImporterTestBase, AnonymousRecords) {
+  auto *Code =
+  R"(
+  struct X {
+struct { int a; };
+struct { int b; };
+  };
+  )";
+  Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
+
+  Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
+
+  auto *X0 =
+  FirstDeclMatcher().match(FromTU0, recordDecl(hasName("X")));
+  auto *X1 =
+  FirstDeclMatcher().match(FromTU1, recordDecl(hasName("X")));
+  Import(X0, Lang_C);
+  Import(X1, Lang_C);
+
+  auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+  // We expect no (ODR) warning during the import.
+  EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
+  EXPECT_EQ(1u,
+DeclCounter().match(ToTU, recordDecl(hasName("X";
+}
+
+TEST_P(ASTImporterTestBase, AnonymousRecordsReversed) {
+  Decl *FromTU0 = getTuDecl(
+  R"(
+  struct X {
+struct { int a; };
+struct { int b; };
+  };
+  )",
+  Lang_C, "input0.c");
+
+  Decl *FromTU1 = getTuDecl(
+  R"(
+  struct X { // reversed order
+struct { int b; };
+struct { int a; };
+  };
+  )",
+  Lang_C, "input1.c");
+
+  auto *X0 =
+  FirstDeclMatcher().match(FromTU0, 

[PATCH] D53655: [ASTImporter] Fix redecl chain of classes and class templates

2018-11-28 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

@aaron.ballman Thanks for your review. I have updated the patch to remove 
`containsInVector`.

> This seems mostly reasonable to me, but @rsmith is more well-versed in this 
> area and may have further comments. You should give him a few days to chime 
> in before committing.

Of course.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53655/new/

https://reviews.llvm.org/D53655



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


[PATCH] D53699: [ASTImporter] Fix inequality of functions with different attributes

2018-11-28 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 175647.
martong added a comment.

- Use ExtInfo in structural equivalency


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53699/new/

https://reviews.llvm.org/D53699

Files:
  lib/AST/ASTStructuralEquivalence.cpp
  unittests/AST/StructuralEquivalenceTest.cpp


Index: unittests/AST/StructuralEquivalenceTest.cpp
===
--- unittests/AST/StructuralEquivalenceTest.cpp
+++ unittests/AST/StructuralEquivalenceTest.cpp
@@ -370,6 +370,15 @@
   EXPECT_FALSE(testStructuralMatch(t));
 }
 
+TEST_F(StructuralEquivalenceFunctionTest,
+FunctionsWithDifferentAttributesButSameTypesShouldBeEqual) {
+  auto t = makeNamedDecls(
+  "__attribute__((noreturn)) void foo();",
+  "  void foo();",
+  Lang_C);
+  EXPECT_TRUE(testStructuralMatch(t));
+}
+
 struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {
 };
 
Index: lib/AST/ASTStructuralEquivalence.cpp
===
--- lib/AST/ASTStructuralEquivalence.cpp
+++ lib/AST/ASTStructuralEquivalence.cpp
@@ -297,6 +297,33 @@
   return true;
 }
 
+/// Determine structural equivalence based on the ExtInfo of functions. This
+/// is inspired by ASTContext::mergeFunctionTypes(), we compare calling
+/// conventions bits but must not compare some other bits, e.g. the noreturn
+/// bit.
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext ,
+ FunctionType::ExtInfo EI1,
+ FunctionType::ExtInfo EI2) {
+  // Compatible functions must have compatible calling conventions.
+  if (EI1.getCC() != EI2.getCC())
+return false;
+
+  // Regparm is part of the calling convention.
+  if (EI1.getHasRegParm() != EI2.getHasRegParm())
+return false;
+  if (EI1.getRegParm() != EI2.getRegParm())
+return false;
+
+  if (EI1.getProducesResult() != EI2.getProducesResult())
+return false;
+  if (EI1.getNoCallerSavedRegs() != EI2.getNoCallerSavedRegs())
+return false;
+  if (EI1.getNoCfCheck() != EI2.getNoCfCheck())
+return false;
+
+  return true;
+}
+
 /// Determine structural equivalence of two types.
 static bool IsStructurallyEquivalent(StructuralEquivalenceContext ,
  QualType T1, QualType T2) {
@@ -540,7 +567,8 @@
 if (!IsStructurallyEquivalent(Context, Function1->getReturnType(),
   Function2->getReturnType()))
   return false;
-if (Function1->getExtInfo() != Function2->getExtInfo())
+if (!IsStructurallyEquivalent(Context, Function1->getExtInfo(),
+  Function2->getExtInfo()))
   return false;
 break;
   }


Index: unittests/AST/StructuralEquivalenceTest.cpp
===
--- unittests/AST/StructuralEquivalenceTest.cpp
+++ unittests/AST/StructuralEquivalenceTest.cpp
@@ -370,6 +370,15 @@
   EXPECT_FALSE(testStructuralMatch(t));
 }
 
+TEST_F(StructuralEquivalenceFunctionTest,
+FunctionsWithDifferentAttributesButSameTypesShouldBeEqual) {
+  auto t = makeNamedDecls(
+  "__attribute__((noreturn)) void foo();",
+  "  void foo();",
+  Lang_C);
+  EXPECT_TRUE(testStructuralMatch(t));
+}
+
 struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {
 };
 
Index: lib/AST/ASTStructuralEquivalence.cpp
===
--- lib/AST/ASTStructuralEquivalence.cpp
+++ lib/AST/ASTStructuralEquivalence.cpp
@@ -297,6 +297,33 @@
   return true;
 }
 
+/// Determine structural equivalence based on the ExtInfo of functions. This
+/// is inspired by ASTContext::mergeFunctionTypes(), we compare calling
+/// conventions bits but must not compare some other bits, e.g. the noreturn
+/// bit.
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext ,
+ FunctionType::ExtInfo EI1,
+ FunctionType::ExtInfo EI2) {
+  // Compatible functions must have compatible calling conventions.
+  if (EI1.getCC() != EI2.getCC())
+return false;
+
+  // Regparm is part of the calling convention.
+  if (EI1.getHasRegParm() != EI2.getHasRegParm())
+return false;
+  if (EI1.getRegParm() != EI2.getRegParm())
+return false;
+
+  if (EI1.getProducesResult() != EI2.getProducesResult())
+return false;
+  if (EI1.getNoCallerSavedRegs() != EI2.getNoCallerSavedRegs())
+return false;
+  if (EI1.getNoCfCheck() != EI2.getNoCfCheck())
+return false;
+
+  return true;
+}
+
 /// Determine structural equivalence of two types.
 static bool IsStructurallyEquivalent(StructuralEquivalenceContext ,
  QualType T1, QualType T2) {
@@ -540,7 +567,8 @@
 if (!IsStructurallyEquivalent(Context, Function1->getReturnType(),
  

[PATCH] D53755: [ASTImporter] Remove import of definition from GetAlreadyImportedOrNull

2018-11-28 Thread Gabor Marton via Phabricator via cfe-commits
martong added a subscriber: teemperor.
martong added a comment.

Hi @shafik ,

Thank you for your review. I have removed the call of `getPrimaryContext`. 
Fortunately, we already have one patch for the `getPrimaryContext` related 
changes, made by @teemperor :  https://reviews.llvm.org/D54898 . I have set 
that patch as the parent of this one (in the stack). Could you please take a 
look on that patch too?


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53755/new/

https://reviews.llvm.org/D53755



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


[PATCH] D53755: [ASTImporter] Remove import of definition from GetAlreadyImportedOrNull

2018-11-28 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 175639.
martong marked an inline comment as done.
martong added a comment.

- Remove call of 'getPrimaryContext'


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53755/new/

https://reviews.llvm.org/D53755

Files:
  include/clang/AST/ASTImporter.h
  lib/AST/ASTImporter.cpp


Index: lib/AST/ASTImporter.cpp
===
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -1580,6 +1580,9 @@
 return Err;
 
   ToD = cast_or_null(Importer.GetAlreadyImportedOrNull(D));
+  if (ToD)
+if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(D, ToD))
+  return Err;
 
   return Error::success();
 }
@@ -7729,17 +7732,12 @@
   return ToAttr;
 }
 
-Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) {
-  llvm::DenseMap::iterator Pos = ImportedDecls.find(FromD);
-  if (Pos != ImportedDecls.end()) {
-Decl *ToD = Pos->second;
-// FIXME: move this call to ImportDeclParts().
-if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(FromD, 
ToD))
-  llvm::consumeError(std::move(Err));
-return ToD;
-  } else {
+Decl *ASTImporter::GetAlreadyImportedOrNull(const Decl *FromD) const {
+  auto Pos = ImportedDecls.find(FromD);
+  if (Pos != ImportedDecls.end())
+return Pos->second;
+  else
 return nullptr;
-  }
 }
 
 Decl *ASTImporter::Import(Decl *FromD) {
Index: include/clang/AST/ASTImporter.h
===
--- include/clang/AST/ASTImporter.h
+++ include/clang/AST/ASTImporter.h
@@ -198,7 +198,7 @@
 /// Return the copy of the given declaration in the "to" context if
 /// it has already been imported from the "from" context.  Otherwise return
 /// NULL.
-Decl *GetAlreadyImportedOrNull(Decl *FromD);
+Decl *GetAlreadyImportedOrNull(const Decl *FromD) const;
 
 /// Import the given declaration context from the "from"
 /// AST context into the "to" AST context.


Index: lib/AST/ASTImporter.cpp
===
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -1580,6 +1580,9 @@
 return Err;
 
   ToD = cast_or_null(Importer.GetAlreadyImportedOrNull(D));
+  if (ToD)
+if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(D, ToD))
+  return Err;
 
   return Error::success();
 }
@@ -7729,17 +7732,12 @@
   return ToAttr;
 }
 
-Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) {
-  llvm::DenseMap::iterator Pos = ImportedDecls.find(FromD);
-  if (Pos != ImportedDecls.end()) {
-Decl *ToD = Pos->second;
-// FIXME: move this call to ImportDeclParts().
-if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(FromD, ToD))
-  llvm::consumeError(std::move(Err));
-return ToD;
-  } else {
+Decl *ASTImporter::GetAlreadyImportedOrNull(const Decl *FromD) const {
+  auto Pos = ImportedDecls.find(FromD);
+  if (Pos != ImportedDecls.end())
+return Pos->second;
+  else
 return nullptr;
-  }
 }
 
 Decl *ASTImporter::Import(Decl *FromD) {
Index: include/clang/AST/ASTImporter.h
===
--- include/clang/AST/ASTImporter.h
+++ include/clang/AST/ASTImporter.h
@@ -198,7 +198,7 @@
 /// Return the copy of the given declaration in the "to" context if
 /// it has already been imported from the "from" context.  Otherwise return
 /// NULL.
-Decl *GetAlreadyImportedOrNull(Decl *FromD);
+Decl *GetAlreadyImportedOrNull(const Decl *FromD) const;
 
 /// Import the given declaration context from the "from"
 /// AST context into the "to" AST context.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53655: [ASTImporter] Fix redecl chain of classes and class templates

2018-11-28 Thread Gabor Marton via Phabricator via cfe-commits
martong marked 4 inline comments as done.
martong added inline comments.



Comment at: include/clang/AST/DeclContextInternals.h:125-129
+  bool containsInVector(const NamedDecl *D) {
+assert(getAsVector() && "Must have a vector at this point");
+DeclsTy  = *getAsVector();
+return is_contained(Vec, D);
+  }

aaron.ballman wrote:
> Given that this is only called in one place and is effectively a one-liner, 
> I'd get rid of this function entirely and replace the call below.
Good catch, thank you.



Comment at: lib/AST/ASTImporter.cpp:2821
 
-  Importer.MapImported(D, D2);
 

a_sidorin wrote:
> Are these lines removed due to move of MapImported into Create helper?
Yes, exactly.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53655/new/

https://reviews.llvm.org/D53655



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


[PATCH] D53699: [ASTImporter] Fix inequality of functions with different attributes

2018-11-28 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

Hi @a_sidorin ,

I have updated the patch as you suggested, to check the equivalence based on 
`ASTContext::mergeFunctionTypes()`.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53699/new/

https://reviews.llvm.org/D53699



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


[PATCH] D53751: [ASTImporter] Added Import functions for transition to new API.

2018-11-28 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

> I didn't actually see this comment get addressed other than to say it won't 
> be a problem in practice, which I'm not certain I agree with. Was there a 
> reason why this got commit before finding out if the reviewer with the 
> concern agrees with your rationale? FWIW, I share the concern that having 
> parallel APIs for any length of time is a dangerous thing. Given that "almost 
> ready to go" is not "ready to go" but there's not an imminent release, I 
> don't understand the rush to commit this.

@aaron.ballman Thanks for your time and review on this.

I completely understand you concern and agree that having such parallel API 
even for a short time is not good. Please let me explain why we chose to do 
this still:
`ASTImporter::Import` functions are used externally by LLDB and CTU as clients. 
However, the functions are used internally too, inside `ASTImporter` and 
`ASTNodeImporter`.  E.g. when we import an expression, then first we use the 
`Import(QualType)` function to import its type.
Our goal is twofold: (1) enforce `ASTImporter` and `ASTNodeImporter` 
implementation functions to always check the result of used import functions 
and (2) make sure that clients can have detailed error information, so e.g. in 
case of CTU we can handle unsupported constructs differently than ODR errors.
As @balazske mentioned we could have changed the API in one lockstep but the 
impact would have been too huge.

In the context of this patch, you can think of the newly introduced 
`Import_New` functions as the internal only functions. I was thinking about 
that we could make them private and `ASTNodeImporter` as a friend,  that way we 
could hide them from clients and then the dual API would cease to exist.


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53751/new/

https://reviews.llvm.org/D53751



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


[PATCH] D55134: [CTU] Add triple/lang mismatch handling

2018-11-30 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176172.
martong added a comment.

- Add lit tests


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55134/new/

https://reviews.llvm.org/D55134

Files:
  include/clang/Basic/DiagnosticCrossTUKinds.td
  include/clang/CrossTU/CrossTranslationUnit.h
  lib/CrossTU/CrossTranslationUnit.cpp
  test/Analysis/ctu-different-triples.cpp
  test/Analysis/ctu-unknown-parts-in-triples.cpp

Index: test/Analysis/ctu-unknown-parts-in-triples.cpp
===
--- /dev/null
+++ test/Analysis/ctu-unknown-parts-in-triples.cpp
@@ -0,0 +1,16 @@
+// We do not expect any error when one part of the triple is unknown, but other
+// known parts are equal.
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection  -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%t/ctudir -verify %s
+
+// expected-no-diagnostics
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: test/Analysis/ctu-different-triples.cpp
===
--- /dev/null
+++ test/Analysis/ctu-different-triples.cpp
@@ -0,0 +1,14 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_cc1 -triple powerpc64-montavista-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%t/ctudir -verify %s
+
+// We expect an error in this file, but without a location.
+// expected-error-re@./ctu-different-triples.cpp:*{{imported AST from {{.*}} had been generated for a different target, current: powerpc64-montavista-linux-gnu, imported: x86_64-pc-linux-gnu}}
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -28,6 +28,36 @@
 #include 
 #include 
 
+namespace llvm {
+// Same as Triple's equality operator, but we check a field only if that is
+// known in both instances.
+bool hasEqualKnownFields(const Triple , const Triple ) {
+  return ((Lhs.getArch() != Triple::UnknownArch &&
+   Rhs.getArch() != Triple::UnknownArch)
+  ? Lhs.getArch() == Rhs.getArch()
+  : true) &&
+ ((Lhs.getSubArch() != Triple::NoSubArch &&
+   Rhs.getSubArch() != Triple::NoSubArch)
+  ? Lhs.getSubArch() == Rhs.getSubArch()
+  : true) &&
+ ((Lhs.getVendor() != Triple::UnknownVendor &&
+   Rhs.getVendor() != Triple::UnknownVendor)
+  ? Lhs.getVendor() == Rhs.getVendor()
+  : true) &&
+ ((Lhs.getOS() != Triple::UnknownOS && Rhs.getOS() != Triple::UnknownOS)
+  ? Lhs.getOS() == Rhs.getOS()
+  : true) &&
+ ((Lhs.getEnvironment() != Triple::UnknownEnvironment &&
+   Rhs.getEnvironment() != Triple::UnknownEnvironment)
+  ? Lhs.getEnvironment() == Rhs.getEnvironment()
+  : true) &&
+ ((Lhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+   Rhs.getObjectFormat() != Triple::UnknownObjectFormat)
+  ? Lhs.getObjectFormat() == Rhs.getObjectFormat()
+  : true);
+}
+}
+
 namespace clang {
 namespace cross_tu {
 
@@ -55,6 +85,10 @@
   return "Failed to load external AST source.";
 case index_error_code::failed_to_generate_usr:
   return "Failed to generate USR.";
+case index_error_code::triple_mismatch:
+  return "Triple mismatch";
+case index_error_code::lang_mismatch:
+  return "Language mismatch";
 }
 llvm_unreachable("Unrecognized index_error_code.");
   }
@@ -166,6 +200,30 @@
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
+  const auto& TripleTo = Context.getTargetInfo().getTriple();
+  const auto& TripleFrom = Unit->getASTContext().getTargetInfo().getTriple();
+  // The imported AST had been generated for a different target.
+  // Some parts of the triple in the loaded ASTContext can be unknown while the
+  // very same parts in the target ASTContext are known. Thus we check for the
+  // known parts only.
+  if (!hasEqualKnownFields(TripleTo, TripleFrom)) {
+// TODO pass the SourceLocation of the CallExpression for more precise
+// diagnostics
+

[PATCH] D55135: [CTU][Analyzer]Add DisplayCTUProgress analyzer switch

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176582.
martong added a comment.

- Change the CTU progress message in the test too


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55135/new/

https://reviews.llvm.org/D55135

Files:
  include/clang/CrossTU/CrossTranslationUnit.h
  include/clang/Driver/CC1Options.td
  include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
  lib/CrossTU/CrossTranslationUnit.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/StaticAnalyzer/Core/CallEvent.cpp
  test/Analysis/ctu-main.cpp

Index: test/Analysis/ctu-main.cpp
===
--- test/Analysis/ctu-main.cpp
+++ test/Analysis/ctu-main.cpp
@@ -3,6 +3,10 @@
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
 // RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -analyzer-display-ctu-progress 2>&1 %s | FileCheck %s
+
+// CHECK: ANALYZE CTU loaded AST file: {{.*}}/ctu-other.cpp
+// CHECK: ANALYZE CTU loaded AST file: {{.*}}/ctu-chain.cpp
 
 #include "ctu-hdr.h"
 
Index: lib/StaticAnalyzer/Core/CallEvent.cpp
===
--- lib/StaticAnalyzer/Core/CallEvent.cpp
+++ lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -560,7 +560,8 @@
   cross_tu::CrossTranslationUnitContext  =
   *Engine->getCrossTranslationUnitContext();
   llvm::Expected CTUDeclOrError =
-  CTUCtx.getCrossTUDefinition(FD, Opts.getCTUDir(), Opts.getCTUIndexName());
+  CTUCtx.getCrossTUDefinition(FD, Opts.getCTUDir(), Opts.getCTUIndexName(),
+  Opts.AnalyzerDisplayCTUProgress);
 
   if (!CTUDeclOrError) {
 handleAllErrors(CTUDeclOrError.takeError(),
Index: lib/Frontend/CompilerInvocation.cpp
===
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -289,6 +289,8 @@
   Opts.NoRetryExhausted = Args.hasArg(OPT_analyzer_disable_retry_exhausted);
   Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers);
   Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress);
+  Opts.AnalyzerDisplayCTUProgress =
+  Args.hasArg(OPT_analyzer_display_ctu_progress);
   Opts.AnalyzeNestedBlocks =
 Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks);
   Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function);
Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -149,14 +149,15 @@
 llvm::Expected
 CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
   StringRef CrossTUDir,
-  StringRef IndexName) {
+  StringRef IndexName,
+  bool DisplayCTUProgress) {
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
 return llvm::make_error(
 index_error_code::failed_to_generate_usr);
   llvm::Expected ASTUnitOrError =
-  loadExternalAST(LookupFnName, CrossTUDir, IndexName);
+  loadExternalAST(LookupFnName, CrossTUDir, IndexName, DisplayCTUProgress);
   if (!ASTUnitOrError)
 return ASTUnitOrError.takeError();
   ASTUnit *Unit = *ASTUnitOrError;
@@ -193,7 +194,8 @@
 }
 
 llvm::Expected CrossTranslationUnitContext::loadExternalAST(
-StringRef LookupName, StringRef CrossTUDir, StringRef IndexName) {
+StringRef LookupName, StringRef CrossTUDir, StringRef IndexName,
+bool DisplayCTUProgress) {
   // FIXME: The current implementation only supports loading functions with
   //a lookup name from a single translation unit. If multiple
   //translation units contains functions with the same lookup name an
@@ -233,6 +235,10 @@
   ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts()));
   Unit = LoadedUnit.get();
   FileASTUnitMap[ASTFileName] = std::move(LoadedUnit);
+  if (DisplayCTUProgress) {
+llvm::errs() << "ANALYZE CTU loaded AST file: "
+ << ASTFileName << "\n";
+  }
 } else {
   Unit = ASTCacheEntry->second.get();
 }
Index: include/clang/StaticAnalyzer/Core/AnalyzerOptions.h

[PATCH] D55135: [CTU][Analyzer]Add DisplayCTUProgress analyzer switch

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176581.
martong marked 4 inline comments as done.
martong added a comment.

- Rename AnalyzerDisplayCtuProgress to Opts.AnalyzerDisplayCTUProgress
- Change the CTU progress message


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55135/new/

https://reviews.llvm.org/D55135

Files:
  include/clang/CrossTU/CrossTranslationUnit.h
  include/clang/Driver/CC1Options.td
  include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
  lib/CrossTU/CrossTranslationUnit.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/StaticAnalyzer/Core/CallEvent.cpp
  test/Analysis/ctu-main.cpp

Index: test/Analysis/ctu-main.cpp
===
--- test/Analysis/ctu-main.cpp
+++ test/Analysis/ctu-main.cpp
@@ -3,6 +3,10 @@
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
 // RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -analyzer-display-ctu-progress 2>&1 %s | FileCheck %s
+
+// CHECK: ANALYZE (CTU loaded AST for source file): {{.*}}/ctu-other.cpp
+// CHECK: ANALYZE (CTU loaded AST for source file): {{.*}}/ctu-chain.cpp
 
 #include "ctu-hdr.h"
 
Index: lib/StaticAnalyzer/Core/CallEvent.cpp
===
--- lib/StaticAnalyzer/Core/CallEvent.cpp
+++ lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -560,7 +560,8 @@
   cross_tu::CrossTranslationUnitContext  =
   *Engine->getCrossTranslationUnitContext();
   llvm::Expected CTUDeclOrError =
-  CTUCtx.getCrossTUDefinition(FD, Opts.getCTUDir(), Opts.getCTUIndexName());
+  CTUCtx.getCrossTUDefinition(FD, Opts.getCTUDir(), Opts.getCTUIndexName(),
+  Opts.AnalyzerDisplayCTUProgress);
 
   if (!CTUDeclOrError) {
 handleAllErrors(CTUDeclOrError.takeError(),
Index: lib/Frontend/CompilerInvocation.cpp
===
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -289,6 +289,8 @@
   Opts.NoRetryExhausted = Args.hasArg(OPT_analyzer_disable_retry_exhausted);
   Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers);
   Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress);
+  Opts.AnalyzerDisplayCTUProgress =
+  Args.hasArg(OPT_analyzer_display_ctu_progress);
   Opts.AnalyzeNestedBlocks =
 Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks);
   Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function);
Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -149,14 +149,15 @@
 llvm::Expected
 CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
   StringRef CrossTUDir,
-  StringRef IndexName) {
+  StringRef IndexName,
+  bool DisplayCTUProgress) {
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
 return llvm::make_error(
 index_error_code::failed_to_generate_usr);
   llvm::Expected ASTUnitOrError =
-  loadExternalAST(LookupFnName, CrossTUDir, IndexName);
+  loadExternalAST(LookupFnName, CrossTUDir, IndexName, DisplayCTUProgress);
   if (!ASTUnitOrError)
 return ASTUnitOrError.takeError();
   ASTUnit *Unit = *ASTUnitOrError;
@@ -193,7 +194,8 @@
 }
 
 llvm::Expected CrossTranslationUnitContext::loadExternalAST(
-StringRef LookupName, StringRef CrossTUDir, StringRef IndexName) {
+StringRef LookupName, StringRef CrossTUDir, StringRef IndexName,
+bool DisplayCTUProgress) {
   // FIXME: The current implementation only supports loading functions with
   //a lookup name from a single translation unit. If multiple
   //translation units contains functions with the same lookup name an
@@ -233,6 +235,10 @@
   ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts()));
   Unit = LoadedUnit.get();
   FileASTUnitMap[ASTFileName] = std::move(LoadedUnit);
+  if (DisplayCTUProgress) {
+llvm::errs() << "ANALYZE CTU loaded AST file: "
+ << ASTFileName << "\n";
+  }
 } else {
   Unit = ASTCacheEntry->second.get();
 }

[PATCH] D55135: [CTU][Analyzer]Add DisplayCTUProgress analyzer switch

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

> Also, almost everywhere CTU is capitalized, so I guess it should be in the 
> field name too.

Ok, I renamed it to have CTU all capitalized.




Comment at: lib/CrossTU/CrossTranslationUnit.cpp:239
+  if (DisplayCTUProgress) {
+llvm::errs() << "ANALYZE (CTU loaded AST for source file): "
+ << ASTFileName << "\n";

a_sidorin wrote:
> I think we can remove parens from the message.
Ok, I removed the parens. And also changed the text from `CTU loaded AST for 
source file` to `CTU loaded AST file` since we dump the path to the AST, not 
the path to the source file from which we generated the AST file.



Comment at: test/Analysis/ctu-main.cpp:6
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze 
-analyzer-checker=core,debug.ExprInspection -analyzer-config 
experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir 
-verify %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze 
-analyzer-checker=core,debug.ExprInspection -analyzer-config 
experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir 
-analyzer-display-ctu-progress 2>&1 %s | FileCheck %s
+

Szelethus wrote:
> I think these RUN lines would really benefit from introducing line breaks.
Yes, I agree. Unfortunately, I could not figure out how to break them. Using a 
simple "\" at around the 80th column gives `Test has unterminated run lines 
(with '\')`. If I use block comments with "\" the same happens. If I use block 
comments and don't use the "\" then the second line is not interpreted. Is it 
really possible to break RUN lines? I could not find anything about that in the 
online docs.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55135/new/

https://reviews.llvm.org/D55135



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


[PATCH] D55135: [CTU][Analyzer]Add DisplayCTUProgress analyzer switch

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176590.
martong marked an inline comment as done.
martong added a comment.

- Break long RUN line


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55135/new/

https://reviews.llvm.org/D55135

Files:
  include/clang/CrossTU/CrossTranslationUnit.h
  include/clang/Driver/CC1Options.td
  include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
  lib/CrossTU/CrossTranslationUnit.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/StaticAnalyzer/Core/CallEvent.cpp
  test/Analysis/ctu-main.cpp

Index: test/Analysis/ctu-main.cpp
===
--- test/Analysis/ctu-main.cpp
+++ test/Analysis/ctu-main.cpp
@@ -3,6 +3,14 @@
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
 // RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%T/ctudir \
+// RUN:   -analyzer-display-ctu-progress 2>&1 %s | FileCheck %s
+
+// CHECK: ANALYZE CTU loaded AST file: {{.*}}/ctu-other.cpp
+// CHECK: ANALYZE CTU loaded AST file: {{.*}}/ctu-chain.cpp
 
 #include "ctu-hdr.h"
 
Index: lib/StaticAnalyzer/Core/CallEvent.cpp
===
--- lib/StaticAnalyzer/Core/CallEvent.cpp
+++ lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -560,7 +560,8 @@
   cross_tu::CrossTranslationUnitContext  =
   *Engine->getCrossTranslationUnitContext();
   llvm::Expected CTUDeclOrError =
-  CTUCtx.getCrossTUDefinition(FD, Opts.getCTUDir(), Opts.getCTUIndexName());
+  CTUCtx.getCrossTUDefinition(FD, Opts.getCTUDir(), Opts.getCTUIndexName(),
+  Opts.AnalyzerDisplayCTUProgress);
 
   if (!CTUDeclOrError) {
 handleAllErrors(CTUDeclOrError.takeError(),
Index: lib/Frontend/CompilerInvocation.cpp
===
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -289,6 +289,8 @@
   Opts.NoRetryExhausted = Args.hasArg(OPT_analyzer_disable_retry_exhausted);
   Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers);
   Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress);
+  Opts.AnalyzerDisplayCTUProgress =
+  Args.hasArg(OPT_analyzer_display_ctu_progress);
   Opts.AnalyzeNestedBlocks =
 Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks);
   Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function);
Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -149,14 +149,15 @@
 llvm::Expected
 CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
   StringRef CrossTUDir,
-  StringRef IndexName) {
+  StringRef IndexName,
+  bool DisplayCTUProgress) {
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
 return llvm::make_error(
 index_error_code::failed_to_generate_usr);
   llvm::Expected ASTUnitOrError =
-  loadExternalAST(LookupFnName, CrossTUDir, IndexName);
+  loadExternalAST(LookupFnName, CrossTUDir, IndexName, DisplayCTUProgress);
   if (!ASTUnitOrError)
 return ASTUnitOrError.takeError();
   ASTUnit *Unit = *ASTUnitOrError;
@@ -193,7 +194,8 @@
 }
 
 llvm::Expected CrossTranslationUnitContext::loadExternalAST(
-StringRef LookupName, StringRef CrossTUDir, StringRef IndexName) {
+StringRef LookupName, StringRef CrossTUDir, StringRef IndexName,
+bool DisplayCTUProgress) {
   // FIXME: The current implementation only supports loading functions with
   //a lookup name from a single translation unit. If multiple
   //translation units contains functions with the same lookup name an
@@ -233,6 +235,10 @@
   ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts()));
   Unit = LoadedUnit.get();
   FileASTUnitMap[ASTFileName] = std::move(LoadedUnit);
+  if (DisplayCTUProgress) {
+llvm::errs() << "ANALYZE CTU loaded AST file: "
+ << ASTFileName << "\n";
+  }
 } else {
   Unit = ASTCacheEntry->second.get();
 }
Index: 

[PATCH] D55135: [CTU][Analyzer]Add DisplayCTUProgress analyzer switch

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong added inline comments.



Comment at: test/Analysis/ctu-main.cpp:6
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze 
-analyzer-checker=core,debug.ExprInspection -analyzer-config 
experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir 
-verify %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze 
-analyzer-checker=core,debug.ExprInspection -analyzer-config 
experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir 
-analyzer-display-ctu-progress 2>&1 %s | FileCheck %s
+

martong wrote:
> Szelethus wrote:
> > I think these RUN lines would really benefit from introducing line breaks.
> Yes, I agree. Unfortunately, I could not figure out how to break them. Using 
> a simple "\" at around the 80th column gives `Test has unterminated run lines 
> (with '\')`. If I use block comments with "\" the same happens. If I use 
> block comments and don't use the "\" then the second line is not interpreted. 
> Is it really possible to break RUN lines? I could not find anything about 
> that in the online docs.
Oh, I just have found your other comment to the other patch. So yes, it is 
indeed possible to break this line. I updated the patch accordingly. The other 
long lines which are already there I am going to change in an independent 
patch: (https://reviews.llvm.org/D55129).


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55135/new/

https://reviews.llvm.org/D55135



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


[PATCH] D55134: [CTU] Add triple/lang mismatch handling

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176584.
martong added a comment.

- Break long RUN lines


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55134/new/

https://reviews.llvm.org/D55134

Files:
  include/clang/Basic/DiagnosticCrossTUKinds.td
  include/clang/CrossTU/CrossTranslationUnit.h
  lib/CrossTU/CrossTranslationUnit.cpp
  test/Analysis/ctu-different-triples.cpp
  test/Analysis/ctu-unknown-parts-in-triples.cpp

Index: test/Analysis/ctu-unknown-parts-in-triples.cpp
===
--- /dev/null
+++ test/Analysis/ctu-unknown-parts-in-triples.cpp
@@ -0,0 +1,21 @@
+// We do not expect any error when one part of the triple is unknown, but other
+// known parts are equal.
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -analyze \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -verify %s
+
+// expected-no-diagnostics
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: test/Analysis/ctu-different-triples.cpp
===
--- /dev/null
+++ test/Analysis/ctu-different-triples.cpp
@@ -0,0 +1,19 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_cc1 -triple powerpc64-montavista-linux-gnu -fsyntax-only \
+// RUN:   -analyze -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -verify %s
+
+// We expect an error in this file, but without a location.
+// expected-error-re@./ctu-different-triples.cpp:*{{imported AST from {{.*}} had been generated for a different target, current: powerpc64-montavista-linux-gnu, imported: x86_64-pc-linux-gnu}}
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -32,6 +32,36 @@
 namespace cross_tu {
 
 namespace {
+
+// Same as Triple's equality operator, but we check a field only if that is
+// known in both instances.
+bool hasEqualKnownFields(const llvm::Triple , const llvm::Triple ) {
+  using llvm::Triple;
+  if (Lhs.getArch() != Triple::UnknownArch &&
+  Rhs.getArch() != Triple::UnknownArch && Lhs.getArch() != Rhs.getArch())
+return false;
+  if (Lhs.getSubArch() != Triple::NoSubArch &&
+  Rhs.getSubArch() != Triple::NoSubArch &&
+  Lhs.getSubArch() != Rhs.getSubArch())
+return false;
+  if (Lhs.getVendor() != Triple::UnknownVendor &&
+  Rhs.getVendor() != Triple::UnknownVendor &&
+  Lhs.getVendor() != Rhs.getVendor())
+return false;
+  if (!Lhs.isOSUnknown() && !Rhs.isOSUnknown() &&
+  Lhs.getOS() != Rhs.getOS())
+return false;
+  if (Lhs.getEnvironment() != Triple::UnknownEnvironment &&
+  Rhs.getEnvironment() != Triple::UnknownEnvironment &&
+  Lhs.getEnvironment() != Rhs.getEnvironment())
+return false;
+  if (Lhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+  Rhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+  Lhs.getObjectFormat() != Rhs.getObjectFormat())
+return false;
+  return true;
+}
+
 // FIXME: This class is will be removed after the transition to llvm::Error.
 class IndexErrorCategory : public std::error_category {
 public:
@@ -55,6 +85,10 @@
   return "Failed to load external AST source.";
 case index_error_code::failed_to_generate_usr:
   return "Failed to generate USR.";
+case index_error_code::triple_mismatch:
+  return "Triple mismatch";
+case index_error_code::lang_mismatch:
+  return "Language mismatch";
 }
 llvm_unreachable("Unrecognized index_error_code.");
   }
@@ -166,6 +200,30 @@
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
+  const auto  = Context.getTargetInfo().getTriple();
+  const auto  = Unit->getASTContext().getTargetInfo().getTriple();
+  // The imported AST had been generated for a different target.
+  // Some parts of the triple in the loaded ASTContext can be unknown while the
+  // very same parts in the target ASTContext are known. Thus we check for the
+  // known parts only.
+  if (!hasEqualKnownFields(TripleTo, TripleFrom)) {
+// TODO: Pass the SourceLocation of the CallExpression for 

[PATCH] D55280: [CTU] Remove redundant error check

2018-12-05 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

@Szelethus @balazske Thanks for your review! The meantime I have discussed with 
@xazax.hun that actually the called `ASTUnit::LoadFromASTFile` function inside 
`loadExternalAST` may return with a nullptr. So, the best is to handle that 
inside `loadExternalAST`.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55280/new/

https://reviews.llvm.org/D55280



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


[PATCH] D55280: [CTU] Remove redundant error check

2018-12-05 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176779.
martong added a comment.

- Return an error from loadExternalAST in case of nullptr


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55280/new/

https://reviews.llvm.org/D55280

Files:
  include/clang/CrossTU/CrossTranslationUnit.h
  lib/CrossTU/CrossTranslationUnit.cpp


Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -160,9 +160,6 @@
   if (!ASTUnitOrError)
 return ASTUnitOrError.takeError();
   ASTUnit *Unit = *ASTUnitOrError;
-  if (!Unit)
-return llvm::make_error(
-index_error_code::failed_to_get_external_ast);
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
@@ -240,6 +237,9 @@
   } else {
 Unit = FnUnitCacheEntry->second;
   }
+  if (!Unit)
+return llvm::make_error(
+index_error_code::failed_to_get_external_ast);
   return Unit;
 }
 
Index: include/clang/CrossTU/CrossTranslationUnit.h
===
--- include/clang/CrossTU/CrossTranslationUnit.h
+++ include/clang/CrossTU/CrossTranslationUnit.h
@@ -118,8 +118,9 @@
   /// \p IndexName. In case the declaration is found in the index the
   /// corresponding AST file will be loaded.
   ///
-  /// \return Returns an ASTUnit that contains the definition of the looked up
-  /// function.
+  /// \return Returns a pointer to the ASTUnit that contains the definition of
+  /// the looked up function or an Error.
+  /// The returned pointer is never a nullptr.
   ///
   /// Note that the AST files should also be in the \p CrossTUDir.
   llvm::Expected loadExternalAST(StringRef LookupName,


Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -160,9 +160,6 @@
   if (!ASTUnitOrError)
 return ASTUnitOrError.takeError();
   ASTUnit *Unit = *ASTUnitOrError;
-  if (!Unit)
-return llvm::make_error(
-index_error_code::failed_to_get_external_ast);
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
@@ -240,6 +237,9 @@
   } else {
 Unit = FnUnitCacheEntry->second;
   }
+  if (!Unit)
+return llvm::make_error(
+index_error_code::failed_to_get_external_ast);
   return Unit;
 }
 
Index: include/clang/CrossTU/CrossTranslationUnit.h
===
--- include/clang/CrossTU/CrossTranslationUnit.h
+++ include/clang/CrossTU/CrossTranslationUnit.h
@@ -118,8 +118,9 @@
   /// \p IndexName. In case the declaration is found in the index the
   /// corresponding AST file will be loaded.
   ///
-  /// \return Returns an ASTUnit that contains the definition of the looked up
-  /// function.
+  /// \return Returns a pointer to the ASTUnit that contains the definition of
+  /// the looked up function or an Error.
+  /// The returned pointer is never a nullptr.
   ///
   /// Note that the AST files should also be in the \p CrossTUDir.
   llvm::Expected loadExternalAST(StringRef LookupName,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55131: [CTU] Add more lit tests and better error handling

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

> Also, maybe it'd be worth making a CTU directory under test/Analysis for CTU 
> related test files.

It is a good point, but I'd do that in the future once we have even more ctu 
related test files. Perhaps together with a new check-clang-analysis-ctu build 
target.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55131/new/

https://reviews.llvm.org/D55131



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


[PATCH] D55131: [CTU] Add more lit tests and better error handling

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176619.
martong marked 8 inline comments as done.
martong added a comment.

- Break long RUN lines
- Clang format the test files
- Use consistent naming style
- Remove braces


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55131/new/

https://reviews.llvm.org/D55131

Files:
  lib/CrossTU/CrossTranslationUnit.cpp
  test/Analysis/Inputs/ctu-other.c
  test/Analysis/Inputs/externalFnMap2.txt
  test/Analysis/ctu-main.c

Index: test/Analysis/ctu-main.c
===
--- /dev/null
+++ test/Analysis/ctu-main.c
@@ -0,0 +1,67 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir2
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir2/ctu-other.c.ast %S/Inputs/ctu-other.c
+// RUN: cp %S/Inputs/externalFnMap2.txt %t/ctudir2/externalFnMap.txt
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -std=c89 -analyze \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir2 \
+// RUN:   -verify %s
+
+void clang_analyzer_eval(int);
+
+// Test typedef and global variable in function.
+typedef struct {
+  int a;
+  int b;
+} FooBar;
+extern FooBar fb;
+int f(int);
+void testGlobalVariable() {
+  clang_analyzer_eval(f(5) == 1); // expected-warning{{TRUE}}
+}
+
+// Test enums.
+int enumCheck(void);
+enum A { x,
+ y,
+ z };
+void testEnum() {
+  clang_analyzer_eval(x == 0);// expected-warning{{TRUE}}
+  clang_analyzer_eval(enumCheck() == 42); // expected-warning{{TRUE}}
+}
+
+// Test that asm import does not fail.
+int inlineAsm();
+int testInlineAsm() {
+  return inlineAsm();
+}
+
+// Test reporting error in a macro.
+struct S;
+int g(struct S *);
+void testMacro(void) {
+  g(0); // expected-warning@Inputs/ctu-other.c:29 {{Access to field 'a' results in a dereference of a null pointer (loaded from variable 'ctx')}}
+}
+
+// The external function prototype is incomplete.
+// warning:implicit functions are prohibited by c99
+void testImplicit() {
+  int res = identImplicit(6);   // external implicit functions are not inlined
+  clang_analyzer_eval(res == 6); // expected-warning{{TRUE}}
+}
+
+// Tests the import of functions that have a struct parameter
+// defined in its prototype.
+struct DataType {
+  int a;
+  int b;
+};
+int structInProto(struct DataType *d);
+void testStructDefInArgument() {
+  struct DataType d;
+  d.a = 1;
+  d.b = 0;
+  clang_analyzer_eval(structInProto() == 0); // expected-warning{{TRUE}} expected-warning{{FALSE}}
+}
Index: test/Analysis/Inputs/externalFnMap2.txt
===
--- /dev/null
+++ test/Analysis/Inputs/externalFnMap2.txt
@@ -0,0 +1,6 @@
+c:@F@inlineAsm ctu-other.c.ast
+c:@F@g ctu-other.c.ast
+c:@F@f ctu-other.c.ast
+c:@F@enumCheck ctu-other.c.ast
+c:@F@identImplicit ctu-other.c.ast
+c:@F@structInProto ctu-other.c.ast
Index: test/Analysis/Inputs/ctu-other.c
===
--- /dev/null
+++ test/Analysis/Inputs/ctu-other.c
@@ -0,0 +1,49 @@
+// Test typedef and global variable in function.
+typedef struct {
+  int a;
+  int b;
+} FooBar;
+FooBar fb;
+int f(int i) {
+  if (fb.a) {
+fb.b = i;
+  }
+  return 1;
+}
+
+// Test enums.
+enum B { x = 42,
+ l,
+ s };
+int enumCheck(void) {
+  return x;
+}
+
+// Test reporting an error in macro definition
+#define MYMACRO(ctx) \
+  ctx->a;
+struct S {
+  int a;
+};
+int g(struct S *ctx) {
+  MYMACRO(ctx);
+  return 0;
+}
+
+// Test that asm import does not fail.
+int inlineAsm() {
+  int res;
+  asm("mov $42, %0"
+  : "=r"(res));
+  return res;
+}
+
+// Implicit function.
+int identImplicit(int in) {
+  return in;
+}
+
+// ASTImporter doesn't support this construct.
+int structInProto(struct DataType {int a;int b; } * d) {
+  return 0;
+}
Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -247,7 +247,9 @@
 CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD) {
   ASTImporter  = getOrCreateASTImporter(FD->getASTContext());
   auto *ToDecl =
-  cast(Importer.Import(const_cast(FD)));
+  cast_or_null(Importer.Import(const_cast(FD)));
+  if (!ToDecl)
+return llvm::make_error(index_error_code::failed_import);
   assert(ToDecl->hasBody());
   assert(FD->hasBody() && "Functions already imported should have body.");
   return ToDecl;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55131: [CTU] Add more lit tests and better error handling

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong added inline comments.



Comment at: test/Analysis/Inputs/ctu-other.c:6
+  int b;
+} foobar;
+

a_sidorin wrote:
> Please use a consistent naming style across the file. There are names 
> starting with capital, having underscores and written like this.
Ok, I renamed the things, I was trying to be consistent with the LLVM style, 
one exception is the name of variables still start with small case.
I also restructured the file a bit and added more comments, so it is more 
cleaner which things belong together to the same test.



Comment at: test/Analysis/ctu-main.c:3-5
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o 
%t/ctudir2/ctu-other.c.ast %S/Inputs/ctu-other.c
+// RUN: cp %S/Inputs/externalFnMap2.txt %t/ctudir2/externalFnMap.txt
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -std=c89 -analyze 
-analyzer-checker=core,debug.ExprInspection  -analyzer-config 
experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%t/ctudir2 
-verify %s

Szelethus wrote:
> Could you please break these lines?
> ```
> // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu %S/Inputs/ctu-other.c \
> // RUN:-emit-pch -o %t/ctudir2/ctu-other.c.ast
> //
> // RUN: cp %S/Inputs/externalFnMap2.txt %t/ctudir2/externalFnMap.txt
> //
> // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -std=c89 
> -analyze -verify %s
> // RUN:   -analyzer-checker=core \
> // RUN:   -analyzer-checker=debug.ExprInspection \
> // RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
> // RUN:   -analyzer-config ctu-dir=%t/ctudir2
> ```
Ok, good point.



Comment at: test/Analysis/ctu-main.c:4
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o 
%t/ctudir2/ctu-other.c.ast %S/Inputs/ctu-other.c
+// RUN: cp %S/Inputs/externalFnMap2.txt %t/ctudir2/externalFnMap.txt
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -std=c89 -analyze 
-analyzer-checker=core,debug.ExprInspection  -analyzer-config 
experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%t/ctudir2 
-verify %s

Szelethus wrote:
> This is a question rather than anything else, why do we have both 
> externalFnMap2.txt and externalFnMap.txt?
`externalFnMap.txt` goes for `ctu-other.cpp`.
`externalFnMap2.txt` goes for `ctu-other.c`.
Perhaps we should rename them in the `Inputs` directory to include the indexed 
file name. E.g. `ctu-other.cpp.externalFnMap.txt`. What do you think?


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55131/new/

https://reviews.llvm.org/D55131



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


[PATCH] D55133: [CTU] Add statistics

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176655.
martong marked an inline comment as done.
martong added a comment.

- Remove braces


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55133/new/

https://reviews.llvm.org/D55133

Files:
  lib/CrossTU/CrossTranslationUnit.cpp


Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -21,6 +21,7 @@
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Index/USRGeneration.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Statistic.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/Path.h"
@@ -32,6 +33,15 @@
 namespace cross_tu {
 
 namespace {
+#define DEBUG_TYPE "CrossTranslationUnit"
+STATISTIC(NumGetCTUCalled, "The # of getCTUDefinition function called");
+STATISTIC(
+NumNotInOtherTU,
+"The # of getCTUDefinition called but the function is not in any other 
TU");
+STATISTIC(NumGetCTUSuccess,
+  "The # of getCTUDefinition successfully returned the "
+  "requested function's body");
+
 // FIXME: This class is will be removed after the transition to llvm::Error.
 class IndexErrorCategory : public std::error_category {
 public:
@@ -151,14 +161,16 @@
   StringRef CrossTUDir,
   StringRef IndexName) {
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
+  ++NumGetCTUCalled;
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
 return llvm::make_error(
 index_error_code::failed_to_generate_usr);
   llvm::Expected ASTUnitOrError =
   loadExternalAST(LookupFnName, CrossTUDir, IndexName);
-  if (!ASTUnitOrError)
+  if (!ASTUnitOrError) {
 return ASTUnitOrError.takeError();
+  }
   ASTUnit *Unit = *ASTUnitOrError;
   if (!Unit)
 return llvm::make_error(
@@ -216,8 +228,10 @@
 }
 
 auto It = FunctionFileMap.find(LookupName);
-if (It == FunctionFileMap.end())
+if (It == FunctionFileMap.end()) {
+  ++NumNotInOtherTU;
   return 
llvm::make_error(index_error_code::missing_definition);
+}
 StringRef ASTFileName = It->second;
 auto ASTCacheEntry = FileASTUnitMap.find(ASTFileName);
 if (ASTCacheEntry == FileASTUnitMap.end()) {
@@ -250,6 +264,7 @@
   cast(Importer.Import(const_cast(FD)));
   assert(ToDecl->hasBody());
   assert(FD->hasBody() && "Functions already imported should have body.");
+  ++NumGetCTUSuccess;
   return ToDecl;
 }
 


Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -21,6 +21,7 @@
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Index/USRGeneration.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Statistic.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/Path.h"
@@ -32,6 +33,15 @@
 namespace cross_tu {
 
 namespace {
+#define DEBUG_TYPE "CrossTranslationUnit"
+STATISTIC(NumGetCTUCalled, "The # of getCTUDefinition function called");
+STATISTIC(
+NumNotInOtherTU,
+"The # of getCTUDefinition called but the function is not in any other TU");
+STATISTIC(NumGetCTUSuccess,
+  "The # of getCTUDefinition successfully returned the "
+  "requested function's body");
+
 // FIXME: This class is will be removed after the transition to llvm::Error.
 class IndexErrorCategory : public std::error_category {
 public:
@@ -151,14 +161,16 @@
   StringRef CrossTUDir,
   StringRef IndexName) {
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
+  ++NumGetCTUCalled;
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
 return llvm::make_error(
 index_error_code::failed_to_generate_usr);
   llvm::Expected ASTUnitOrError =
   loadExternalAST(LookupFnName, CrossTUDir, IndexName);
-  if (!ASTUnitOrError)
+  if (!ASTUnitOrError) {
 return ASTUnitOrError.takeError();
+  }
   ASTUnit *Unit = *ASTUnitOrError;
   if (!Unit)
 return llvm::make_error(
@@ -216,8 +228,10 @@
 }
 
 auto It = FunctionFileMap.find(LookupName);
-if (It == FunctionFileMap.end())
+if (It == FunctionFileMap.end()) {
+  ++NumNotInOtherTU;
   return llvm::make_error(index_error_code::missing_definition);
+}
 StringRef ASTFileName = It->second;
 auto ASTCacheEntry = FileASTUnitMap.find(ASTFileName);
 if (ASTCacheEntry == FileASTUnitMap.end()) {
@@ -250,6 +264,7 @@
   cast(Importer.Import(const_cast(FD)));
   assert(ToDecl->hasBody());
   assert(FD->hasBody() && 

[PATCH] D55129: [CTU] Eliminate race condition in CTU lit tests

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176660.
martong added a comment.

- Use rm, mkdir and break long RUN lines


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55129/new/

https://reviews.llvm.org/D55129

Files:
  test/Analysis/ctu-main.cpp


Index: test/Analysis/ctu-main.cpp
===
--- test/Analysis/ctu-main.cpp
+++ test/Analysis/ctu-main.cpp
@@ -1,8 +1,15 @@
-// RUN: mkdir -p %T/ctudir
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o 
%T/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o 
%T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
-// RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze 
-analyzer-checker=core,debug.ExprInspection -analyzer-config 
experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir 
-verify %s
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/
+// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -verify %s
 
 #include "ctu-hdr.h"
 


Index: test/Analysis/ctu-main.cpp
===
--- test/Analysis/ctu-main.cpp
+++ test/Analysis/ctu-main.cpp
@@ -1,8 +1,15 @@
-// RUN: mkdir -p %T/ctudir
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
-// RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/
+// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -verify %s
 
 #include "ctu-hdr.h"
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53655: [ASTImporter] Fix redecl chain of classes and class templates

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

@rsmith ping


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53655/new/

https://reviews.llvm.org/D53655



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


[PATCH] D55134: [CTU] Add triple/lang mismatch handling

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176672.
martong added a comment.

- Forgot to rename err_ctu_incompat_triple -> warn_ctu_incompat_triple


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55134/new/

https://reviews.llvm.org/D55134

Files:
  include/clang/Basic/DiagnosticCrossTUKinds.td
  include/clang/Basic/DiagnosticGroups.td
  include/clang/CrossTU/CrossTranslationUnit.h
  lib/CrossTU/CrossTranslationUnit.cpp
  test/Analysis/ctu-different-triples.cpp
  test/Analysis/ctu-unknown-parts-in-triples.cpp

Index: test/Analysis/ctu-unknown-parts-in-triples.cpp
===
--- /dev/null
+++ test/Analysis/ctu-unknown-parts-in-triples.cpp
@@ -0,0 +1,22 @@
+// We do not expect any error when one part of the triple is unknown, but other
+// known parts are equal.
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -analyze \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -Werror=ctu \
+// RUN:   -verify %s
+
+// expected-no-diagnostics
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: test/Analysis/ctu-different-triples.cpp
===
--- /dev/null
+++ test/Analysis/ctu-different-triples.cpp
@@ -0,0 +1,20 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_cc1 -triple powerpc64-montavista-linux-gnu -fsyntax-only \
+// RUN:   -analyze -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -Werror=ctu \
+// RUN:   -verify %s
+
+// We expect an error in this file, but without a location.
+// expected-error-re@./ctu-different-triples.cpp:*{{imported AST from {{.*}} had been generated for a different target, current: powerpc64-montavista-linux-gnu, imported: x86_64-pc-linux-gnu}}
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -32,6 +32,36 @@
 namespace cross_tu {
 
 namespace {
+
+// Same as Triple's equality operator, but we check a field only if that is
+// known in both instances.
+bool hasEqualKnownFields(const llvm::Triple , const llvm::Triple ) {
+  using llvm::Triple;
+  if (Lhs.getArch() != Triple::UnknownArch &&
+  Rhs.getArch() != Triple::UnknownArch && Lhs.getArch() != Rhs.getArch())
+return false;
+  if (Lhs.getSubArch() != Triple::NoSubArch &&
+  Rhs.getSubArch() != Triple::NoSubArch &&
+  Lhs.getSubArch() != Rhs.getSubArch())
+return false;
+  if (Lhs.getVendor() != Triple::UnknownVendor &&
+  Rhs.getVendor() != Triple::UnknownVendor &&
+  Lhs.getVendor() != Rhs.getVendor())
+return false;
+  if (!Lhs.isOSUnknown() && !Rhs.isOSUnknown() &&
+  Lhs.getOS() != Rhs.getOS())
+return false;
+  if (Lhs.getEnvironment() != Triple::UnknownEnvironment &&
+  Rhs.getEnvironment() != Triple::UnknownEnvironment &&
+  Lhs.getEnvironment() != Rhs.getEnvironment())
+return false;
+  if (Lhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+  Rhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+  Lhs.getObjectFormat() != Rhs.getObjectFormat())
+return false;
+  return true;
+}
+
 // FIXME: This class is will be removed after the transition to llvm::Error.
 class IndexErrorCategory : public std::error_category {
 public:
@@ -55,6 +85,10 @@
   return "Failed to load external AST source.";
 case index_error_code::failed_to_generate_usr:
   return "Failed to generate USR.";
+case index_error_code::triple_mismatch:
+  return "Triple mismatch";
+case index_error_code::lang_mismatch:
+  return "Language mismatch";
 }
 llvm_unreachable("Unrecognized index_error_code.");
   }
@@ -166,6 +200,30 @@
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
+  const auto  = Context.getTargetInfo().getTriple();
+  const auto  = Unit->getASTContext().getTargetInfo().getTriple();
+  // The imported AST had been generated for a different target.
+  // Some parts of the triple in the loaded ASTContext can be unknown while the
+  // very same parts in the target ASTContext are known. Thus we check for the
+  

[PATCH] D55133: [CTU] Add statistics

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

> Sorry, but I don't understand the meaning of some options. Could you please 
> explain what are NumNoUnit and NumNotInOtherTU and what is the difference 
> between them?

Your point is absolutely true. They are the same, I think at some point some 
time ago they were different (in our fork), now it is just redundancy. So I 
removed `NumNoUnit`.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55133/new/

https://reviews.llvm.org/D55133



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


[PATCH] D55133: [CTU] Add statistics

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176654.
martong added a comment.

- Remove NumNoUnit


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55133/new/

https://reviews.llvm.org/D55133

Files:
  lib/CrossTU/CrossTranslationUnit.cpp


Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -21,6 +21,7 @@
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Index/USRGeneration.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Statistic.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/Path.h"
@@ -32,6 +33,15 @@
 namespace cross_tu {
 
 namespace {
+#define DEBUG_TYPE "CrossTranslationUnit"
+STATISTIC(NumGetCTUCalled, "The # of getCTUDefinition function called");
+STATISTIC(
+NumNotInOtherTU,
+"The # of getCTUDefinition called but the function is not in any other 
TU");
+STATISTIC(NumGetCTUSuccess,
+  "The # of getCTUDefinition successfully returned the "
+  "requested function's body");
+
 // FIXME: This class is will be removed after the transition to llvm::Error.
 class IndexErrorCategory : public std::error_category {
 public:
@@ -151,18 +161,21 @@
   StringRef CrossTUDir,
   StringRef IndexName) {
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
+  ++NumGetCTUCalled;
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
 return llvm::make_error(
 index_error_code::failed_to_generate_usr);
   llvm::Expected ASTUnitOrError =
   loadExternalAST(LookupFnName, CrossTUDir, IndexName);
-  if (!ASTUnitOrError)
+  if (!ASTUnitOrError) {
 return ASTUnitOrError.takeError();
+  }
   ASTUnit *Unit = *ASTUnitOrError;
-  if (!Unit)
+  if (!Unit) {
 return llvm::make_error(
 index_error_code::failed_to_get_external_ast);
+  }
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
@@ -216,8 +229,10 @@
 }
 
 auto It = FunctionFileMap.find(LookupName);
-if (It == FunctionFileMap.end())
+if (It == FunctionFileMap.end()) {
+  ++NumNotInOtherTU;
   return 
llvm::make_error(index_error_code::missing_definition);
+}
 StringRef ASTFileName = It->second;
 auto ASTCacheEntry = FileASTUnitMap.find(ASTFileName);
 if (ASTCacheEntry == FileASTUnitMap.end()) {
@@ -250,6 +265,7 @@
   cast(Importer.Import(const_cast(FD)));
   assert(ToDecl->hasBody());
   assert(FD->hasBody() && "Functions already imported should have body.");
+  ++NumGetCTUSuccess;
   return ToDecl;
 }
 


Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -21,6 +21,7 @@
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Index/USRGeneration.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Statistic.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/Path.h"
@@ -32,6 +33,15 @@
 namespace cross_tu {
 
 namespace {
+#define DEBUG_TYPE "CrossTranslationUnit"
+STATISTIC(NumGetCTUCalled, "The # of getCTUDefinition function called");
+STATISTIC(
+NumNotInOtherTU,
+"The # of getCTUDefinition called but the function is not in any other TU");
+STATISTIC(NumGetCTUSuccess,
+  "The # of getCTUDefinition successfully returned the "
+  "requested function's body");
+
 // FIXME: This class is will be removed after the transition to llvm::Error.
 class IndexErrorCategory : public std::error_category {
 public:
@@ -151,18 +161,21 @@
   StringRef CrossTUDir,
   StringRef IndexName) {
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
+  ++NumGetCTUCalled;
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
 return llvm::make_error(
 index_error_code::failed_to_generate_usr);
   llvm::Expected ASTUnitOrError =
   loadExternalAST(LookupFnName, CrossTUDir, IndexName);
-  if (!ASTUnitOrError)
+  if (!ASTUnitOrError) {
 return ASTUnitOrError.takeError();
+  }
   ASTUnit *Unit = *ASTUnitOrError;
-  if (!Unit)
+  if (!Unit) {
 return llvm::make_error(
 index_error_code::failed_to_get_external_ast);
+  }
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
@@ -216,8 +229,10 @@
 }
 
 auto It = FunctionFileMap.find(LookupName);
-if (It == FunctionFileMap.end())
+if (It == FunctionFileMap.end()) {
+  ++NumNotInOtherTU;
   return 

[PATCH] D55280: [CTU] Remove redundant error check

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong created this revision.
martong added reviewers: xazax.hun, a_sidorin, Szelethus, balazske.
Herald added subscribers: cfe-commits, gamesh411, dkrupp, rnkovacs.

In loadExternalAST we normally return with either an error or with a valid
ASTUnit pointer which should not be a nullptr.
However, in the call site we did a superfluous check for being a nullptr.


Repository:
  rC Clang

https://reviews.llvm.org/D55280

Files:
  include/clang/CrossTU/CrossTranslationUnit.h
  lib/CrossTU/CrossTranslationUnit.cpp


Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -51,8 +51,6 @@
   return "Missing definition from the index file.";
 case index_error_code::failed_import:
   return "Failed to import the definition.";
-case index_error_code::failed_to_get_external_ast:
-  return "Failed to load external AST source.";
 case index_error_code::failed_to_generate_usr:
   return "Failed to generate USR.";
 }
@@ -160,9 +158,6 @@
   if (!ASTUnitOrError)
 return ASTUnitOrError.takeError();
   ASTUnit *Unit = *ASTUnitOrError;
-  if (!Unit)
-return llvm::make_error(
-index_error_code::failed_to_get_external_ast);
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
@@ -240,6 +235,7 @@
   } else {
 Unit = FnUnitCacheEntry->second;
   }
+  assert(Unit);
   return Unit;
 }
 
Index: include/clang/CrossTU/CrossTranslationUnit.h
===
--- include/clang/CrossTU/CrossTranslationUnit.h
+++ include/clang/CrossTU/CrossTranslationUnit.h
@@ -40,7 +40,6 @@
   multiple_definitions,
   missing_definition,
   failed_import,
-  failed_to_get_external_ast,
   failed_to_generate_usr
 };
 
@@ -118,8 +117,8 @@
   /// \p IndexName. In case the declaration is found in the index the
   /// corresponding AST file will be loaded.
   ///
-  /// \return Returns an ASTUnit that contains the definition of the looked up
-  /// function.
+  /// \return Returns a pointer to the ASTUnit that contains the definition of
+  /// the looked up function. The pointer should not be a nullptr.
   ///
   /// Note that the AST files should also be in the \p CrossTUDir.
   llvm::Expected loadExternalAST(StringRef LookupName,


Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -51,8 +51,6 @@
   return "Missing definition from the index file.";
 case index_error_code::failed_import:
   return "Failed to import the definition.";
-case index_error_code::failed_to_get_external_ast:
-  return "Failed to load external AST source.";
 case index_error_code::failed_to_generate_usr:
   return "Failed to generate USR.";
 }
@@ -160,9 +158,6 @@
   if (!ASTUnitOrError)
 return ASTUnitOrError.takeError();
   ASTUnit *Unit = *ASTUnitOrError;
-  if (!Unit)
-return llvm::make_error(
-index_error_code::failed_to_get_external_ast);
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
@@ -240,6 +235,7 @@
   } else {
 Unit = FnUnitCacheEntry->second;
   }
+  assert(Unit);
   return Unit;
 }
 
Index: include/clang/CrossTU/CrossTranslationUnit.h
===
--- include/clang/CrossTU/CrossTranslationUnit.h
+++ include/clang/CrossTU/CrossTranslationUnit.h
@@ -40,7 +40,6 @@
   multiple_definitions,
   missing_definition,
   failed_import,
-  failed_to_get_external_ast,
   failed_to_generate_usr
 };
 
@@ -118,8 +117,8 @@
   /// \p IndexName. In case the declaration is found in the index the
   /// corresponding AST file will be loaded.
   ///
-  /// \return Returns an ASTUnit that contains the definition of the looked up
-  /// function.
+  /// \return Returns a pointer to the ASTUnit that contains the definition of
+  /// the looked up function. The pointer should not be a nullptr.
   ///
   /// Note that the AST files should also be in the \p CrossTUDir.
   llvm::Expected loadExternalAST(StringRef LookupName,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55133: [CTU] Add statistics

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

>> Sorry, but I don't understand the meaning of some options. Could you please 
>> explain what are NumNoUnit and NumNotInOtherTU and what is the difference 
>> between them?



> Your point is absolutely true. They are the same, I think at some point some 
> time ago they were different (in our fork), now it is just redundancy. So I 
> removed `NumNoUnit`.

They are the same because in `loadExternalAST` we must return witn a non 
nullptr value, so it seems like the second check is redundant here:

  if (!ASTUnitOrError) {
return ASTUnitOrError.takeError();
  }
  ASTUnit *Unit = *ASTUnitOrError;
  if (!Unit)
return llvm::make_error(
index_error_code::failed_to_get_external_ast);

I am going to open another patch to fix this.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55133/new/

https://reviews.llvm.org/D55133



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


[PATCH] D55134: [CTU] Add triple/lang mismatch handling

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong added inline comments.



Comment at: include/clang/Basic/DiagnosticCrossTUKinds.td:19
+
+def err_ctu_incompat_triple : Error<
+  "imported AST from '%0' had been generated for a different target, current: 
%1, imported: %2">;

xazax.hun wrote:
> I am not sure if we want this to be an error. The analysis could continue 
> without any problems if we do not actually merge the two ASTs. So maybe 
> having a warning only is better. My concern is that once we have this error, 
> there would be no way to analyze mixed language (C/C++) projects cleanly 
> using CTU.
Okay, I agree, I changed it to be a warning by default.



Comment at: lib/CrossTU/CrossTranslationUnit.cpp:212
+// diagnostics.
+Context.getDiagnostics().Report(diag::err_ctu_incompat_triple)
+<< Unit->getMainFileName() << TripleTo.str() << TripleFrom.str();

xazax.hun wrote:
> I think we should not emit an error here. It should be up to the caller (the 
> user of the library) to decide if she wants to handle this as an error, 
> warnings, or just suppress these kinds of problems. I would rather extend 
> `emitCrossTUDiagnostics` as a shorthand for the user if emitting an error is 
> the desired behavior.
 I would prefer to exploit the capabilities of the `DiagEngine`, instead of 
extending the interface of `CrossTranslationUnitContext`.
By using a `DiagGroup` we can upgrade the warning to be an error, so I just 
changed it to be like that.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55134/new/

https://reviews.llvm.org/D55134



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


[PATCH] D55134: [CTU] Add triple/lang mismatch handling

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176671.
martong marked 4 inline comments as done.
martong added a comment.

- Diagnose a warning (which may be upgradable to an error)


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55134/new/

https://reviews.llvm.org/D55134

Files:
  include/clang/Basic/DiagnosticCrossTUKinds.td
  include/clang/Basic/DiagnosticGroups.td
  include/clang/CrossTU/CrossTranslationUnit.h
  lib/CrossTU/CrossTranslationUnit.cpp
  test/Analysis/ctu-different-triples.cpp
  test/Analysis/ctu-unknown-parts-in-triples.cpp

Index: test/Analysis/ctu-unknown-parts-in-triples.cpp
===
--- /dev/null
+++ test/Analysis/ctu-unknown-parts-in-triples.cpp
@@ -0,0 +1,22 @@
+// We do not expect any error when one part of the triple is unknown, but other
+// known parts are equal.
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -analyze \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -Werror=ctu \
+// RUN:   -verify %s
+
+// expected-no-diagnostics
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: test/Analysis/ctu-different-triples.cpp
===
--- /dev/null
+++ test/Analysis/ctu-different-triples.cpp
@@ -0,0 +1,20 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_cc1 -triple powerpc64-montavista-linux-gnu -fsyntax-only \
+// RUN:   -analyze -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -Werror=ctu \
+// RUN:   -verify %s
+
+// We expect an error in this file, but without a location.
+// expected-error-re@./ctu-different-triples.cpp:*{{imported AST from {{.*}} had been generated for a different target, current: powerpc64-montavista-linux-gnu, imported: x86_64-pc-linux-gnu}}
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -32,6 +32,36 @@
 namespace cross_tu {
 
 namespace {
+
+// Same as Triple's equality operator, but we check a field only if that is
+// known in both instances.
+bool hasEqualKnownFields(const llvm::Triple , const llvm::Triple ) {
+  using llvm::Triple;
+  if (Lhs.getArch() != Triple::UnknownArch &&
+  Rhs.getArch() != Triple::UnknownArch && Lhs.getArch() != Rhs.getArch())
+return false;
+  if (Lhs.getSubArch() != Triple::NoSubArch &&
+  Rhs.getSubArch() != Triple::NoSubArch &&
+  Lhs.getSubArch() != Rhs.getSubArch())
+return false;
+  if (Lhs.getVendor() != Triple::UnknownVendor &&
+  Rhs.getVendor() != Triple::UnknownVendor &&
+  Lhs.getVendor() != Rhs.getVendor())
+return false;
+  if (!Lhs.isOSUnknown() && !Rhs.isOSUnknown() &&
+  Lhs.getOS() != Rhs.getOS())
+return false;
+  if (Lhs.getEnvironment() != Triple::UnknownEnvironment &&
+  Rhs.getEnvironment() != Triple::UnknownEnvironment &&
+  Lhs.getEnvironment() != Rhs.getEnvironment())
+return false;
+  if (Lhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+  Rhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+  Lhs.getObjectFormat() != Rhs.getObjectFormat())
+return false;
+  return true;
+}
+
 // FIXME: This class is will be removed after the transition to llvm::Error.
 class IndexErrorCategory : public std::error_category {
 public:
@@ -55,6 +85,10 @@
   return "Failed to load external AST source.";
 case index_error_code::failed_to_generate_usr:
   return "Failed to generate USR.";
+case index_error_code::triple_mismatch:
+  return "Triple mismatch";
+case index_error_code::lang_mismatch:
+  return "Language mismatch";
 }
 llvm_unreachable("Unrecognized index_error_code.");
   }
@@ -166,6 +200,30 @@
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
+  const auto  = Context.getTargetInfo().getTriple();
+  const auto  = Unit->getASTContext().getTargetInfo().getTriple();
+  // The imported AST had been generated for a different target.
+  // Some parts of the triple in the loaded ASTContext can be unknown while the
+  // very same parts in the target ASTContext are 

[PATCH] D55135: [CTU][Analyzer]Add DisplayCTUProgress analyzer switch

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176653.
martong added a comment.

- Use clang_analyze_cc1
- Change to be an analyzer config option


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55135/new/

https://reviews.llvm.org/D55135

Files:
  include/clang/CrossTU/CrossTranslationUnit.h
  include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
  lib/CrossTU/CrossTranslationUnit.cpp
  lib/StaticAnalyzer/Core/CallEvent.cpp
  test/Analysis/analyzer-config.c
  test/Analysis/ctu-main.cpp

Index: test/Analysis/ctu-main.cpp
===
--- test/Analysis/ctu-main.cpp
+++ test/Analysis/ctu-main.cpp
@@ -3,6 +3,14 @@
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
 // RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%T/ctudir \
+// RUN:   -analyzer-config display-ctu-progress=true 2>&1 %s | FileCheck %s
+
+// CHECK: ANALYZE CTU loaded AST file: {{.*}}/ctu-other.cpp
+// CHECK: ANALYZE CTU loaded AST file: {{.*}}/ctu-chain.cpp
 
 #include "ctu-hdr.h"
 
Index: test/Analysis/analyzer-config.c
===
--- test/Analysis/analyzer-config.c
+++ test/Analysis/analyzer-config.c
@@ -21,6 +21,7 @@
 // CHECK-NEXT: crosscheck-with-z3 = false
 // CHECK-NEXT: ctu-dir = ""
 // CHECK-NEXT: ctu-index-name = externalFnMap.txt
+// CHECK-NEXT: display-ctu-progress = false
 // CHECK-NEXT: eagerly-assume = true
 // CHECK-NEXT: elide-constructors = true
 // CHECK-NEXT: expand-macros = false
@@ -51,4 +52,4 @@
 // CHECK-NEXT: unroll-loops = false
 // CHECK-NEXT: widen-loops = false
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 48
+// CHECK-NEXT: num-entries = 49
Index: lib/StaticAnalyzer/Core/CallEvent.cpp
===
--- lib/StaticAnalyzer/Core/CallEvent.cpp
+++ lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -560,8 +560,8 @@
   cross_tu::CrossTranslationUnitContext  =
   *Engine->getCrossTranslationUnitContext();
   llvm::Expected CTUDeclOrError =
-  CTUCtx.getCrossTUDefinition(FD, Opts.CTUDir,
-  Opts.CTUIndexName);
+  CTUCtx.getCrossTUDefinition(FD, Opts.CTUDir, Opts.CTUIndexName,
+  Opts.DisplayCTUProgress);
 
   if (!CTUDeclOrError) {
 handleAllErrors(CTUDeclOrError.takeError(),
Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -149,14 +149,15 @@
 llvm::Expected
 CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
   StringRef CrossTUDir,
-  StringRef IndexName) {
+  StringRef IndexName,
+  bool DisplayCTUProgress) {
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
 return llvm::make_error(
 index_error_code::failed_to_generate_usr);
   llvm::Expected ASTUnitOrError =
-  loadExternalAST(LookupFnName, CrossTUDir, IndexName);
+  loadExternalAST(LookupFnName, CrossTUDir, IndexName, DisplayCTUProgress);
   if (!ASTUnitOrError)
 return ASTUnitOrError.takeError();
   ASTUnit *Unit = *ASTUnitOrError;
@@ -193,7 +194,8 @@
 }
 
 llvm::Expected CrossTranslationUnitContext::loadExternalAST(
-StringRef LookupName, StringRef CrossTUDir, StringRef IndexName) {
+StringRef LookupName, StringRef CrossTUDir, StringRef IndexName,
+bool DisplayCTUProgress) {
   // FIXME: The current implementation only supports loading functions with
   //a lookup name from a single translation unit. If multiple
   //translation units contains functions with the same lookup name an
@@ -233,6 +235,10 @@
   ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts()));
   Unit = LoadedUnit.get();
   FileASTUnitMap[ASTFileName] = std::move(LoadedUnit);
+  if (DisplayCTUProgress) {
+llvm::errs() << "ANALYZE CTU loaded AST file: "
+ << ASTFileName << "\n";
+  }
 } else {
   Unit = ASTCacheEntry->second.get();
 }
Index: include/clang/StaticAnalyzer/Core/AnalyzerOptions.def

[PATCH] D55135: [CTU][Analyzer]Add DisplayCTUProgress analyzer switch

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

> should be an -analyzer-config option.

Ok, just changed it to be.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55135/new/

https://reviews.llvm.org/D55135



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


[PATCH] D55280: [CTU] Make loadExternalAST return with non nullptr on success

2018-12-05 Thread Gabor Marton via Phabricator via cfe-commits
martong marked an inline comment as done.
martong added inline comments.



Comment at: lib/CrossTU/CrossTranslationUnit.cpp:147
 
 llvm::Expected
 CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,

balazske wrote:
> Szelethus wrote:
> > Would it be worth to add a comment that this function never returns with 
> > `nullptr` on success?
> Even on failure not. Failure should be `Error`, success is a non-null pointer.
Yes, you are right. 
We should indicate that in the documentation of this function that it can not 
return with a nullptr on success. I think we should do that in here 
https://reviews.llvm.org/D55131 because there we do check that the `ToDecl` is 
not a nullptr.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55280/new/

https://reviews.llvm.org/D55280



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


[PATCH] D55131: [CTU] Add more lit tests and better error handling

2018-12-05 Thread Gabor Marton via Phabricator via cfe-commits
martong marked an inline comment as done.
martong added inline comments.



Comment at: lib/CrossTU/CrossTranslationUnit.cpp:247
 llvm::Expected
 CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD) {
   ASTImporter  = getOrCreateASTImporter(FD->getASTContext());

TODO: add a comment that this function never returns with nullptr on success. 
And consequently `CrossTranslationUnitContext::getCrossTUDefinition` neither.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55131/new/

https://reviews.llvm.org/D55131



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


[PATCH] D55134: [CTU] Add triple/lang mismatch handling

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong marked 2 inline comments as done.
martong added inline comments.



Comment at: lib/CrossTU/CrossTranslationUnit.cpp:212
+// diagnostics.
+Context.getDiagnostics().Report(diag::err_ctu_incompat_triple)
+<< Unit->getMainFileName() << TripleTo.str() << TripleFrom.str();

xazax.hun wrote:
> martong wrote:
> > xazax.hun wrote:
> > > I think we should not emit an error here. It should be up to the caller 
> > > (the user of the library) to decide if she wants to handle this as an 
> > > error, warnings, or just suppress these kinds of problems. I would rather 
> > > extend `emitCrossTUDiagnostics` as a shorthand for the user if emitting 
> > > an error is the desired behavior.
> >  I would prefer to exploit the capabilities of the `DiagEngine`, instead of 
> > extending the interface of `CrossTranslationUnitContext`.
> > By using a `DiagGroup` we can upgrade the warning to be an error, so I just 
> > changed it to be like that.
> You do not need the extend the interface. There is already a function for 
> that below. Also, the user might not want to display a warning either but do 
> something else, like generate a log message. 
Ah, okay, I missed that. Now I added a case to that function. Still, I think 
having a `DiagGroup` is useful anyway.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55134/new/

https://reviews.llvm.org/D55134



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


[PATCH] D55134: [CTU] Add triple/lang mismatch handling

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176687.
martong added a comment.

- Use clang_analyze_cc1


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55134/new/

https://reviews.llvm.org/D55134

Files:
  include/clang/Basic/DiagnosticCrossTUKinds.td
  include/clang/Basic/DiagnosticGroups.td
  include/clang/CrossTU/CrossTranslationUnit.h
  lib/CrossTU/CrossTranslationUnit.cpp
  test/Analysis/ctu-different-triples.cpp
  test/Analysis/ctu-unknown-parts-in-triples.cpp

Index: test/Analysis/ctu-unknown-parts-in-triples.cpp
===
--- /dev/null
+++ test/Analysis/ctu-unknown-parts-in-triples.cpp
@@ -0,0 +1,22 @@
+// We do not expect any error when one part of the triple is unknown, but other
+// known parts are equal.
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux-gnu \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -Werror=ctu \
+// RUN:   -verify %s
+
+// expected-no-diagnostics
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: test/Analysis/ctu-different-triples.cpp
===
--- /dev/null
+++ test/Analysis/ctu-different-triples.cpp
@@ -0,0 +1,20 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_analyze_cc1 -triple powerpc64-montavista-linux-gnu \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -Werror=ctu \
+// RUN:   -verify %s
+
+// We expect an error in this file, but without a location.
+// expected-error-re@./ctu-different-triples.cpp:*{{imported AST from {{.*}} had been generated for a different target, current: powerpc64-montavista-linux-gnu, imported: x86_64-pc-linux-gnu}}
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -32,6 +32,36 @@
 namespace cross_tu {
 
 namespace {
+
+// Same as Triple's equality operator, but we check a field only if that is
+// known in both instances.
+bool hasEqualKnownFields(const llvm::Triple , const llvm::Triple ) {
+  using llvm::Triple;
+  if (Lhs.getArch() != Triple::UnknownArch &&
+  Rhs.getArch() != Triple::UnknownArch && Lhs.getArch() != Rhs.getArch())
+return false;
+  if (Lhs.getSubArch() != Triple::NoSubArch &&
+  Rhs.getSubArch() != Triple::NoSubArch &&
+  Lhs.getSubArch() != Rhs.getSubArch())
+return false;
+  if (Lhs.getVendor() != Triple::UnknownVendor &&
+  Rhs.getVendor() != Triple::UnknownVendor &&
+  Lhs.getVendor() != Rhs.getVendor())
+return false;
+  if (!Lhs.isOSUnknown() && !Rhs.isOSUnknown() &&
+  Lhs.getOS() != Rhs.getOS())
+return false;
+  if (Lhs.getEnvironment() != Triple::UnknownEnvironment &&
+  Rhs.getEnvironment() != Triple::UnknownEnvironment &&
+  Lhs.getEnvironment() != Rhs.getEnvironment())
+return false;
+  if (Lhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+  Rhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+  Lhs.getObjectFormat() != Rhs.getObjectFormat())
+return false;
+  return true;
+}
+
 // FIXME: This class is will be removed after the transition to llvm::Error.
 class IndexErrorCategory : public std::error_category {
 public:
@@ -55,6 +85,10 @@
   return "Failed to load external AST source.";
 case index_error_code::failed_to_generate_usr:
   return "Failed to generate USR.";
+case index_error_code::triple_mismatch:
+  return "Triple mismatch";
+case index_error_code::lang_mismatch:
+  return "Language mismatch";
 }
 llvm_unreachable("Unrecognized index_error_code.");
   }
@@ -166,6 +200,31 @@
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
+  const llvm::Triple  = Context.getTargetInfo().getTriple();
+  const llvm::Triple  =
+  Unit->getASTContext().getTargetInfo().getTriple();
+  // The imported AST had been generated for a different target.
+  // Some parts of the triple in the loaded ASTContext can be unknown while the
+  // very same parts in the target ASTContext are known. Thus we check for the
+  // known parts only.
+  if 

[PATCH] D55134: [CTU] Add triple/lang mismatch handling

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

> We should probably prefer %clang_analyze_cc1 to %clang_cc1 -analyze here too.

Ok, changed that.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55134/new/

https://reviews.llvm.org/D55134



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


[PATCH] D55133: [CTU] Add statistics

2018-12-07 Thread Gabor Marton via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL348584: [CTU] Add statistics (authored by martong, committed 
by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D55133?vs=176655=177173#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55133/new/

https://reviews.llvm.org/D55133

Files:
  cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp


Index: cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
===
--- cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
+++ cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
@@ -21,6 +21,7 @@
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Index/USRGeneration.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Statistic.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/Path.h"
@@ -32,6 +33,15 @@
 namespace cross_tu {
 
 namespace {
+#define DEBUG_TYPE "CrossTranslationUnit"
+STATISTIC(NumGetCTUCalled, "The # of getCTUDefinition function called");
+STATISTIC(
+NumNotInOtherTU,
+"The # of getCTUDefinition called but the function is not in any other 
TU");
+STATISTIC(NumGetCTUSuccess,
+  "The # of getCTUDefinition successfully returned the "
+  "requested function's body");
+
 // FIXME: This class is will be removed after the transition to llvm::Error.
 class IndexErrorCategory : public std::error_category {
 public:
@@ -151,6 +161,7 @@
   StringRef CrossTUDir,
   StringRef IndexName) {
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
+  ++NumGetCTUCalled;
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
 return llvm::make_error(
@@ -216,8 +227,10 @@
 }
 
 auto It = FunctionFileMap.find(LookupName);
-if (It == FunctionFileMap.end())
+if (It == FunctionFileMap.end()) {
+  ++NumNotInOtherTU;
   return 
llvm::make_error(index_error_code::missing_definition);
+}
 StringRef ASTFileName = It->second;
 auto ASTCacheEntry = FileASTUnitMap.find(ASTFileName);
 if (ASTCacheEntry == FileASTUnitMap.end()) {
@@ -250,6 +263,7 @@
   cast(Importer.Import(const_cast(FD)));
   assert(ToDecl->hasBody());
   assert(FD->hasBody() && "Functions already imported should have body.");
+  ++NumGetCTUSuccess;
   return ToDecl;
 }
 


Index: cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
===
--- cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
+++ cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
@@ -21,6 +21,7 @@
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Index/USRGeneration.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Statistic.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/Path.h"
@@ -32,6 +33,15 @@
 namespace cross_tu {
 
 namespace {
+#define DEBUG_TYPE "CrossTranslationUnit"
+STATISTIC(NumGetCTUCalled, "The # of getCTUDefinition function called");
+STATISTIC(
+NumNotInOtherTU,
+"The # of getCTUDefinition called but the function is not in any other TU");
+STATISTIC(NumGetCTUSuccess,
+  "The # of getCTUDefinition successfully returned the "
+  "requested function's body");
+
 // FIXME: This class is will be removed after the transition to llvm::Error.
 class IndexErrorCategory : public std::error_category {
 public:
@@ -151,6 +161,7 @@
   StringRef CrossTUDir,
   StringRef IndexName) {
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
+  ++NumGetCTUCalled;
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
 return llvm::make_error(
@@ -216,8 +227,10 @@
 }
 
 auto It = FunctionFileMap.find(LookupName);
-if (It == FunctionFileMap.end())
+if (It == FunctionFileMap.end()) {
+  ++NumNotInOtherTU;
   return llvm::make_error(index_error_code::missing_definition);
+}
 StringRef ASTFileName = It->second;
 auto ASTCacheEntry = FileASTUnitMap.find(ASTFileName);
 if (ASTCacheEntry == FileASTUnitMap.end()) {
@@ -250,6 +263,7 @@
   cast(Importer.Import(const_cast(FD)));
   assert(ToDecl->hasBody());
   assert(FD->hasBody() && "Functions already imported should have body.");
+  ++NumGetCTUSuccess;
   return ToDecl;
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55133: [CTU] Add statistics

2018-12-07 Thread Gabor Marton via Phabricator via cfe-commits
martong marked 2 inline comments as done.
martong added inline comments.



Comment at: lib/CrossTU/CrossTranslationUnit.cpp:171
   loadExternalAST(LookupFnName, CrossTUDir, IndexName);
-  if (!ASTUnitOrError)
+  if (!ASTUnitOrError) {
 return ASTUnitOrError.takeError();

a_sidorin wrote:
> We can omit braces here.
Ok, thanks, I changed that.


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55133/new/

https://reviews.llvm.org/D55133



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


[PATCH] D55132: [CTU] Add asserts to protect invariants

2018-12-07 Thread Gabor Marton via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL348586: [CTU] Add asserts to protect invariants (authored by 
martong, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D55132?vs=176151=177177#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55132/new/

https://reviews.llvm.org/D55132

Files:
  cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp


Index: cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
===
--- cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
+++ cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
@@ -160,6 +160,7 @@
 CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
   StringRef CrossTUDir,
   StringRef IndexName) {
+  assert(FD && "FD is missing, bad call to this function!");
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
   ++NumGetCTUCalled;
   const std::string LookupFnName = getLookupName(FD);
@@ -258,6 +259,8 @@
 
 llvm::Expected
 CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD) {
+  assert(FD->hasBody() && "Functions to be imported should have body.");
+
   ASTImporter  = getOrCreateASTImporter(FD->getASTContext());
   auto *ToDecl =
   cast(Importer.Import(const_cast(FD)));


Index: cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
===
--- cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
+++ cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
@@ -160,6 +160,7 @@
 CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
   StringRef CrossTUDir,
   StringRef IndexName) {
+  assert(FD && "FD is missing, bad call to this function!");
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
   ++NumGetCTUCalled;
   const std::string LookupFnName = getLookupName(FD);
@@ -258,6 +259,8 @@
 
 llvm::Expected
 CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD) {
+  assert(FD->hasBody() && "Functions to be imported should have body.");
+
   ASTImporter  = getOrCreateASTImporter(FD->getASTContext());
   auto *ToDecl =
   cast(Importer.Import(const_cast(FD)));
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55131: [CTU] Add more lit tests and better error handling

2018-12-07 Thread Gabor Marton via Phabricator via cfe-commits
martong marked 2 inline comments as done.
martong added inline comments.



Comment at: test/Analysis/ctu-main.c:4
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o 
%t/ctudir2/ctu-other.c.ast %S/Inputs/ctu-other.c
+// RUN: cp %S/Inputs/externalFnMap2.txt %t/ctudir2/externalFnMap.txt
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -std=c89 -analyze 
-analyzer-checker=core,debug.ExprInspection  -analyzer-config 
experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%t/ctudir2 
-verify %s

Szelethus wrote:
> martong wrote:
> > Szelethus wrote:
> > > This is a question rather than anything else, why do we have both 
> > > externalFnMap2.txt and externalFnMap.txt?
> > `externalFnMap.txt` goes for `ctu-other.cpp`.
> > `externalFnMap2.txt` goes for `ctu-other.c`.
> > Perhaps we should rename them in the `Inputs` directory to include the 
> > indexed file name. E.g. `ctu-other.cpp.externalFnMap.txt`. What do you 
> > think?
> Sounds great! :)
Ok, I have renamed the ExternalFnMap files.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55131/new/

https://reviews.llvm.org/D55131



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


[PATCH] D55131: [CTU] Add more lit tests and better error handling

2018-12-07 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 177170.
martong marked an inline comment as done.
martong added a comment.

- Rename externalFnMap files


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55131/new/

https://reviews.llvm.org/D55131

Files:
  lib/CrossTU/CrossTranslationUnit.cpp
  test/Analysis/Inputs/ctu-other.c
  test/Analysis/Inputs/ctu-other.c.externalFnMap.txt
  test/Analysis/Inputs/ctu-other.cpp.externalFnMap.txt
  test/Analysis/Inputs/externalFnMap.txt
  test/Analysis/ctu-main.c
  test/Analysis/ctu-main.cpp

Index: test/Analysis/ctu-main.cpp
===
--- test/Analysis/ctu-main.cpp
+++ test/Analysis/ctu-main.cpp
@@ -1,7 +1,7 @@
 // RUN: mkdir -p %T/ctudir
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
-// RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/
+// RUN: cp %S/Inputs/ctu-other.cpp.externalFnMap.txt %T/ctudir/externalFnMap.txt
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s
 
 #include "ctu-hdr.h"
Index: test/Analysis/ctu-main.c
===
--- /dev/null
+++ test/Analysis/ctu-main.c
@@ -0,0 +1,67 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir2
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir2/ctu-other.c.ast %S/Inputs/ctu-other.c
+// RUN: cp %S/Inputs/ctu-other.c.externalFnMap.txt %t/ctudir2/externalFnMap.txt
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -std=c89 -analyze \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir2 \
+// RUN:   -verify %s
+
+void clang_analyzer_eval(int);
+
+// Test typedef and global variable in function.
+typedef struct {
+  int a;
+  int b;
+} FooBar;
+extern FooBar fb;
+int f(int);
+void testGlobalVariable() {
+  clang_analyzer_eval(f(5) == 1); // expected-warning{{TRUE}}
+}
+
+// Test enums.
+int enumCheck(void);
+enum A { x,
+ y,
+ z };
+void testEnum() {
+  clang_analyzer_eval(x == 0);// expected-warning{{TRUE}}
+  clang_analyzer_eval(enumCheck() == 42); // expected-warning{{TRUE}}
+}
+
+// Test that asm import does not fail.
+int inlineAsm();
+int testInlineAsm() {
+  return inlineAsm();
+}
+
+// Test reporting error in a macro.
+struct S;
+int g(struct S *);
+void testMacro(void) {
+  g(0); // expected-warning@Inputs/ctu-other.c:29 {{Access to field 'a' results in a dereference of a null pointer (loaded from variable 'ctx')}}
+}
+
+// The external function prototype is incomplete.
+// warning:implicit functions are prohibited by c99
+void testImplicit() {
+  int res = identImplicit(6);   // external implicit functions are not inlined
+  clang_analyzer_eval(res == 6); // expected-warning{{TRUE}}
+}
+
+// Tests the import of functions that have a struct parameter
+// defined in its prototype.
+struct DataType {
+  int a;
+  int b;
+};
+int structInProto(struct DataType *d);
+void testStructDefInArgument() {
+  struct DataType d;
+  d.a = 1;
+  d.b = 0;
+  clang_analyzer_eval(structInProto() == 0); // expected-warning{{TRUE}} expected-warning{{FALSE}}
+}
Index: test/Analysis/Inputs/externalFnMap.txt
===
--- /dev/null
+++ test/Analysis/Inputs/externalFnMap.txt
@@ -1,15 +0,0 @@
-c:@N@chns@F@chf1#I# ctu-other.cpp.ast
-c:@N@myns@N@embed_ns@F@fens#I# ctu-other.cpp.ast
-c:@F@g#I# ctu-other.cpp.ast
-c:@S@mycls@F@fscl#I#S ctu-other.cpp.ast
-c:@S@mycls@F@fcl#I# ctu-other.cpp.ast
-c:@N@myns@S@embed_cls@F@fecl#I# ctu-other.cpp.ast
-c:@S@mycls@S@embed_cls2@F@fecl2#I# ctu-other.cpp.ast
-c:@F@f#I# ctu-other.cpp.ast
-c:@N@myns@F@fns#I# ctu-other.cpp.ast
-c:@F@h#I# ctu-other.cpp.ast
-c:@F@h_chain#I# ctu-chain.cpp.ast
-c:@N@chns@S@chcls@F@chf4#I# ctu-chain.cpp.ast
-c:@N@chns@F@chf2#I# ctu-chain.cpp.ast
-c:@F@fun_using_anon_struct#I# ctu-other.cpp.ast
-c:@F@other_macro_diag#I# ctu-other.cpp.ast
Index: test/Analysis/Inputs/ctu-other.c.externalFnMap.txt
===
--- /dev/null
+++ test/Analysis/Inputs/ctu-other.c.externalFnMap.txt
@@ -0,0 +1,6 @@
+c:@F@inlineAsm ctu-other.c.ast
+c:@F@g ctu-other.c.ast
+c:@F@f ctu-other.c.ast
+c:@F@enumCheck ctu-other.c.ast
+c:@F@identImplicit ctu-other.c.ast
+c:@F@structInProto ctu-other.c.ast
Index: test/Analysis/Inputs/ctu-other.c
===
--- /dev/null
+++ test/Analysis/Inputs/ctu-other.c
@@ -0,0 +1,49 @@
+// Test typedef and global variable in 

[PATCH] D55129: [CTU] Eliminate race condition in CTU lit tests

2018-12-07 Thread Gabor Marton via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL348587: [CTU] Eliminate race condition in CTU lit tests 
(authored by martong, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55129/new/

https://reviews.llvm.org/D55129

Files:
  cfe/trunk/test/Analysis/ctu-main.cpp


Index: cfe/trunk/test/Analysis/ctu-main.cpp
===
--- cfe/trunk/test/Analysis/ctu-main.cpp
+++ cfe/trunk/test/Analysis/ctu-main.cpp
@@ -1,8 +1,15 @@
-// RUN: mkdir -p %T/ctudir
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o 
%T/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o 
%T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
-// RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze 
-analyzer-checker=core,debug.ExprInspection -analyzer-config 
experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir 
-verify %s
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/
+// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -verify %s
 
 #include "ctu-hdr.h"
 


Index: cfe/trunk/test/Analysis/ctu-main.cpp
===
--- cfe/trunk/test/Analysis/ctu-main.cpp
+++ cfe/trunk/test/Analysis/ctu-main.cpp
@@ -1,8 +1,15 @@
-// RUN: mkdir -p %T/ctudir
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
-// RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/
+// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -verify %s
 
 #include "ctu-hdr.h"
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55135: [CTU][Analyzer]Add DisplayCTUProgress analyzer switch

2018-12-07 Thread Gabor Marton via Phabricator via cfe-commits
martong marked an inline comment as done.
martong added a comment.

> While Static Analyzer is the only client of CTU library at the moment, we 
> might have more in the future. I would not use the phrase ANALYZE in the log 
> message. Once this is resolved the rest looks good.

Ok, I removed the "ANALYZE " prefix from the log message.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55135/new/

https://reviews.llvm.org/D55135



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


[PATCH] D55135: [CTU][Analyzer]Add DisplayCTUProgress analyzer switch

2018-12-07 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 177204.
martong added a comment.

- Remove 'ANALYZE ' prefix from the log message


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55135/new/

https://reviews.llvm.org/D55135

Files:
  include/clang/CrossTU/CrossTranslationUnit.h
  include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
  lib/CrossTU/CrossTranslationUnit.cpp
  lib/StaticAnalyzer/Core/CallEvent.cpp
  test/Analysis/analyzer-config.c
  test/Analysis/ctu-main.cpp

Index: test/Analysis/ctu-main.cpp
===
--- test/Analysis/ctu-main.cpp
+++ test/Analysis/ctu-main.cpp
@@ -3,6 +3,14 @@
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
 // RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%T/ctudir \
+// RUN:   -analyzer-config display-ctu-progress=true 2>&1 %s | FileCheck %s
+
+// CHECK: ANALYZE CTU loaded AST file: {{.*}}/ctu-other.cpp
+// CHECK: ANALYZE CTU loaded AST file: {{.*}}/ctu-chain.cpp
 
 #include "ctu-hdr.h"
 
Index: test/Analysis/analyzer-config.c
===
--- test/Analysis/analyzer-config.c
+++ test/Analysis/analyzer-config.c
@@ -21,6 +21,7 @@
 // CHECK-NEXT: crosscheck-with-z3 = false
 // CHECK-NEXT: ctu-dir = ""
 // CHECK-NEXT: ctu-index-name = externalFnMap.txt
+// CHECK-NEXT: display-ctu-progress = false
 // CHECK-NEXT: eagerly-assume = true
 // CHECK-NEXT: elide-constructors = true
 // CHECK-NEXT: expand-macros = false
@@ -51,4 +52,4 @@
 // CHECK-NEXT: unroll-loops = false
 // CHECK-NEXT: widen-loops = false
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 48
+// CHECK-NEXT: num-entries = 49
Index: lib/StaticAnalyzer/Core/CallEvent.cpp
===
--- lib/StaticAnalyzer/Core/CallEvent.cpp
+++ lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -560,8 +560,8 @@
   cross_tu::CrossTranslationUnitContext  =
   *Engine->getCrossTranslationUnitContext();
   llvm::Expected CTUDeclOrError =
-  CTUCtx.getCrossTUDefinition(FD, Opts.CTUDir,
-  Opts.CTUIndexName);
+  CTUCtx.getCrossTUDefinition(FD, Opts.CTUDir, Opts.CTUIndexName,
+  Opts.DisplayCTUProgress);
 
   if (!CTUDeclOrError) {
 handleAllErrors(CTUDeclOrError.takeError(),
Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -149,14 +149,15 @@
 llvm::Expected
 CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
   StringRef CrossTUDir,
-  StringRef IndexName) {
+  StringRef IndexName,
+  bool DisplayCTUProgress) {
   assert(!FD->hasBody() && "FD has a definition in current translation unit!");
   const std::string LookupFnName = getLookupName(FD);
   if (LookupFnName.empty())
 return llvm::make_error(
 index_error_code::failed_to_generate_usr);
   llvm::Expected ASTUnitOrError =
-  loadExternalAST(LookupFnName, CrossTUDir, IndexName);
+  loadExternalAST(LookupFnName, CrossTUDir, IndexName, DisplayCTUProgress);
   if (!ASTUnitOrError)
 return ASTUnitOrError.takeError();
   ASTUnit *Unit = *ASTUnitOrError;
@@ -193,7 +194,8 @@
 }
 
 llvm::Expected CrossTranslationUnitContext::loadExternalAST(
-StringRef LookupName, StringRef CrossTUDir, StringRef IndexName) {
+StringRef LookupName, StringRef CrossTUDir, StringRef IndexName,
+bool DisplayCTUProgress) {
   // FIXME: The current implementation only supports loading functions with
   //a lookup name from a single translation unit. If multiple
   //translation units contains functions with the same lookup name an
@@ -233,6 +235,10 @@
   ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts()));
   Unit = LoadedUnit.get();
   FileASTUnitMap[ASTFileName] = std::move(LoadedUnit);
+  if (DisplayCTUProgress) {
+llvm::errs() << "CTU loaded AST file: "
+ << ASTFileName << "\n";
+  }
 } else {
   Unit = ASTCacheEntry->second.get();
 }
Index: include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
===
--- 

[PATCH] D55131: [CTU] Add more lit tests and better error handling

2018-12-07 Thread Gabor Marton via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL348605: [CTU] Add more lit tests and better error handling 
(authored by martong, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D55131?vs=177170=177223#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55131/new/

https://reviews.llvm.org/D55131

Files:
  cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
  cfe/trunk/test/Analysis/Inputs/ctu-other.c
  cfe/trunk/test/Analysis/Inputs/ctu-other.c.externalFnMap.txt
  cfe/trunk/test/Analysis/Inputs/ctu-other.cpp.externalFnMap.txt
  cfe/trunk/test/Analysis/Inputs/externalFnMap.txt
  cfe/trunk/test/Analysis/ctu-main.c
  cfe/trunk/test/Analysis/ctu-main.cpp

Index: cfe/trunk/test/Analysis/Inputs/ctu-other.cpp.externalFnMap.txt
===
--- cfe/trunk/test/Analysis/Inputs/ctu-other.cpp.externalFnMap.txt
+++ cfe/trunk/test/Analysis/Inputs/ctu-other.cpp.externalFnMap.txt
@@ -0,0 +1,15 @@
+c:@N@chns@F@chf1#I# ctu-other.cpp.ast
+c:@N@myns@N@embed_ns@F@fens#I# ctu-other.cpp.ast
+c:@F@g#I# ctu-other.cpp.ast
+c:@S@mycls@F@fscl#I#S ctu-other.cpp.ast
+c:@S@mycls@F@fcl#I# ctu-other.cpp.ast
+c:@N@myns@S@embed_cls@F@fecl#I# ctu-other.cpp.ast
+c:@S@mycls@S@embed_cls2@F@fecl2#I# ctu-other.cpp.ast
+c:@F@f#I# ctu-other.cpp.ast
+c:@N@myns@F@fns#I# ctu-other.cpp.ast
+c:@F@h#I# ctu-other.cpp.ast
+c:@F@h_chain#I# ctu-chain.cpp.ast
+c:@N@chns@S@chcls@F@chf4#I# ctu-chain.cpp.ast
+c:@N@chns@F@chf2#I# ctu-chain.cpp.ast
+c:@F@fun_using_anon_struct#I# ctu-other.cpp.ast
+c:@F@other_macro_diag#I# ctu-other.cpp.ast
Index: cfe/trunk/test/Analysis/Inputs/ctu-other.c.externalFnMap.txt
===
--- cfe/trunk/test/Analysis/Inputs/ctu-other.c.externalFnMap.txt
+++ cfe/trunk/test/Analysis/Inputs/ctu-other.c.externalFnMap.txt
@@ -0,0 +1,6 @@
+c:@F@inlineAsm ctu-other.c.ast
+c:@F@g ctu-other.c.ast
+c:@F@f ctu-other.c.ast
+c:@F@enumCheck ctu-other.c.ast
+c:@F@identImplicit ctu-other.c.ast
+c:@F@structInProto ctu-other.c.ast
Index: cfe/trunk/test/Analysis/Inputs/ctu-other.c
===
--- cfe/trunk/test/Analysis/Inputs/ctu-other.c
+++ cfe/trunk/test/Analysis/Inputs/ctu-other.c
@@ -0,0 +1,49 @@
+// Test typedef and global variable in function.
+typedef struct {
+  int a;
+  int b;
+} FooBar;
+FooBar fb;
+int f(int i) {
+  if (fb.a) {
+fb.b = i;
+  }
+  return 1;
+}
+
+// Test enums.
+enum B { x = 42,
+ l,
+ s };
+int enumCheck(void) {
+  return x;
+}
+
+// Test reporting an error in macro definition
+#define MYMACRO(ctx) \
+  ctx->a;
+struct S {
+  int a;
+};
+int g(struct S *ctx) {
+  MYMACRO(ctx);
+  return 0;
+}
+
+// Test that asm import does not fail.
+int inlineAsm() {
+  int res;
+  asm("mov $42, %0"
+  : "=r"(res));
+  return res;
+}
+
+// Implicit function.
+int identImplicit(int in) {
+  return in;
+}
+
+// ASTImporter doesn't support this construct.
+int structInProto(struct DataType {int a;int b; } * d) {
+  return 0;
+}
Index: cfe/trunk/test/Analysis/ctu-main.c
===
--- cfe/trunk/test/Analysis/ctu-main.c
+++ cfe/trunk/test/Analysis/ctu-main.c
@@ -0,0 +1,67 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir2
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir2/ctu-other.c.ast %S/Inputs/ctu-other.c
+// RUN: cp %S/Inputs/ctu-other.c.externalFnMap.txt %t/ctudir2/externalFnMap.txt
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -std=c89 -analyze \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir2 \
+// RUN:   -verify %s
+
+void clang_analyzer_eval(int);
+
+// Test typedef and global variable in function.
+typedef struct {
+  int a;
+  int b;
+} FooBar;
+extern FooBar fb;
+int f(int);
+void testGlobalVariable() {
+  clang_analyzer_eval(f(5) == 1); // expected-warning{{TRUE}}
+}
+
+// Test enums.
+int enumCheck(void);
+enum A { x,
+ y,
+ z };
+void testEnum() {
+  clang_analyzer_eval(x == 0);// expected-warning{{TRUE}}
+  clang_analyzer_eval(enumCheck() == 42); // expected-warning{{TRUE}}
+}
+
+// Test that asm import does not fail.
+int inlineAsm();
+int testInlineAsm() {
+  return inlineAsm();
+}
+
+// Test reporting error in a macro.
+struct S;
+int g(struct S *);
+void testMacro(void) {
+  g(0); // expected-warning@Inputs/ctu-other.c:29 {{Access to field 'a' results in a dereference of a null pointer (loaded from variable 'ctx')}}
+}
+
+// The external function prototype is incomplete.
+// warning:implicit functions are prohibited by c99
+void testImplicit() {
+  int res = identImplicit(6);   // external implicit functions are not inlined
+ 

[PATCH] D55134: [CTU] Add triple/lang mismatch handling

2018-12-07 Thread Gabor Marton via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL348610: [CTU] Add triple/lang mismatch handling (authored by 
martong, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D55134?vs=176687=177228#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55134/new/

https://reviews.llvm.org/D55134

Files:
  cfe/trunk/include/clang/Basic/DiagnosticCrossTUKinds.td
  cfe/trunk/include/clang/Basic/DiagnosticGroups.td
  cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h
  cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
  cfe/trunk/test/Analysis/ctu-different-triples.cpp
  cfe/trunk/test/Analysis/ctu-unknown-parts-in-triples.cpp

Index: cfe/trunk/test/Analysis/ctu-different-triples.cpp
===
--- cfe/trunk/test/Analysis/ctu-different-triples.cpp
+++ cfe/trunk/test/Analysis/ctu-different-triples.cpp
@@ -0,0 +1,20 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/ctu-other.cpp.externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_analyze_cc1 -triple powerpc64-montavista-linux-gnu \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -Werror=ctu \
+// RUN:   -verify %s
+
+// We expect an error in this file, but without a location.
+// expected-error-re@./ctu-different-triples.cpp:*{{imported AST from {{.*}} had been generated for a different target, current: powerpc64-montavista-linux-gnu, imported: x86_64-pc-linux-gnu}}
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: cfe/trunk/test/Analysis/ctu-unknown-parts-in-triples.cpp
===
--- cfe/trunk/test/Analysis/ctu-unknown-parts-in-triples.cpp
+++ cfe/trunk/test/Analysis/ctu-unknown-parts-in-triples.cpp
@@ -0,0 +1,22 @@
+// We do not expect any error when one part of the triple is unknown, but other
+// known parts are equal.
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/ctu-other.cpp.externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux-gnu \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -Werror=ctu \
+// RUN:   -verify %s
+
+// expected-no-diagnostics
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
===
--- cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
+++ cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
@@ -33,6 +33,7 @@
 namespace cross_tu {
 
 namespace {
+
 #define DEBUG_TYPE "CrossTranslationUnit"
 STATISTIC(NumGetCTUCalled, "The # of getCTUDefinition function called");
 STATISTIC(
@@ -41,6 +42,37 @@
 STATISTIC(NumGetCTUSuccess,
   "The # of getCTUDefinition successfully returned the "
   "requested function's body");
+STATISTIC(NumTripleMismatch, "The # of triple mismatches");
+STATISTIC(NumLangMismatch, "The # of language mismatches");
+
+// Same as Triple's equality operator, but we check a field only if that is
+// known in both instances.
+bool hasEqualKnownFields(const llvm::Triple , const llvm::Triple ) {
+  using llvm::Triple;
+  if (Lhs.getArch() != Triple::UnknownArch &&
+  Rhs.getArch() != Triple::UnknownArch && Lhs.getArch() != Rhs.getArch())
+return false;
+  if (Lhs.getSubArch() != Triple::NoSubArch &&
+  Rhs.getSubArch() != Triple::NoSubArch &&
+  Lhs.getSubArch() != Rhs.getSubArch())
+return false;
+  if (Lhs.getVendor() != Triple::UnknownVendor &&
+  Rhs.getVendor() != Triple::UnknownVendor &&
+  Lhs.getVendor() != Rhs.getVendor())
+return false;
+  if (!Lhs.isOSUnknown() && !Rhs.isOSUnknown() &&
+  Lhs.getOS() != Rhs.getOS())
+return false;
+  if (Lhs.getEnvironment() != Triple::UnknownEnvironment &&
+  Rhs.getEnvironment() != Triple::UnknownEnvironment &&
+  Lhs.getEnvironment() != Rhs.getEnvironment())
+return false;
+  if (Lhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+  Rhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+  Lhs.getObjectFormat() != Rhs.getObjectFormat())
+return false;
+  return true;
+}
 
 // FIXME: This class is will be removed after the transition to llvm::Error.
 class IndexErrorCategory : public std::error_category {
@@ -65,6 +97,10 @@
   return "Failed to load external AST source.";
 case 

[PATCH] D55135: [CTU][Analyzer]Add DisplayCTUProgress analyzer switch

2018-12-07 Thread Gabor Marton via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL348594: [CTU] Add DisplayCTUProgress analyzer switch 
(authored by martong, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D55135?vs=177204=177208#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55135/new/

https://reviews.llvm.org/D55135

Files:
  cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h
  cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
  cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
  cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
  cfe/trunk/test/Analysis/analyzer-config.c
  cfe/trunk/test/Analysis/ctu-main.cpp

Index: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
===
--- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
@@ -283,6 +283,11 @@
 "expanded and included in the plist output.",
 false)
 
+ANALYZER_OPTION(bool, DisplayCTUProgress, "display-ctu-progress",
+"Whether to emit verbose output about "
+"the analyzer's progress related to ctu.",
+false)
+
 //===--===//
 // Unsinged analyzer options.
 //===--===//
Index: cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h
===
--- cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h
+++ cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h
@@ -108,7 +108,7 @@
   /// Note that the AST files should also be in the \p CrossTUDir.
   llvm::Expected
   getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir,
-   StringRef IndexName);
+   StringRef IndexName, bool DisplayCTUProgress = false);
 
   /// This function loads a function definition from an external AST
   ///file.
@@ -124,7 +124,8 @@
   /// Note that the AST files should also be in the \p CrossTUDir.
   llvm::Expected loadExternalAST(StringRef LookupName,
 StringRef CrossTUDir,
-StringRef IndexName);
+StringRef IndexName,
+bool DisplayCTUProgress = false);
 
   /// This function merges a definition from a separate AST Unit into
   ///the current one which was created by the compiler instance that
Index: cfe/trunk/test/Analysis/analyzer-config.c
===
--- cfe/trunk/test/Analysis/analyzer-config.c
+++ cfe/trunk/test/Analysis/analyzer-config.c
@@ -21,6 +21,7 @@
 // CHECK-NEXT: crosscheck-with-z3 = false
 // CHECK-NEXT: ctu-dir = ""
 // CHECK-NEXT: ctu-index-name = externalFnMap.txt
+// CHECK-NEXT: display-ctu-progress = false
 // CHECK-NEXT: eagerly-assume = true
 // CHECK-NEXT: elide-constructors = true
 // CHECK-NEXT: expand-macros = false
@@ -51,4 +52,4 @@
 // CHECK-NEXT: unroll-loops = false
 // CHECK-NEXT: widen-loops = false
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 48
+// CHECK-NEXT: num-entries = 49
Index: cfe/trunk/test/Analysis/ctu-main.cpp
===
--- cfe/trunk/test/Analysis/ctu-main.cpp
+++ cfe/trunk/test/Analysis/ctu-main.cpp
@@ -10,6 +10,14 @@
 // RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
 // RUN:   -analyzer-config ctu-dir=%t/ctudir \
 // RUN:   -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -analyzer-config display-ctu-progress=true 2>&1 %s | FileCheck %s
+
+// CHECK: CTU loaded AST file: {{.*}}/ctu-other.cpp
+// CHECK: CTU loaded AST file: {{.*}}/ctu-chain.cpp
 
 #include "ctu-hdr.h"
 
Index: cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
===
--- cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
+++ cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
@@ -159,7 +159,8 @@
 llvm::Expected
 CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
   StringRef CrossTUDir,
-  StringRef IndexName) {
+  StringRef IndexName,
+  bool DisplayCTUProgress) {
   assert(FD && "FD is missing, bad call to this function!");
   assert(!FD->hasBody() && "FD has a definition in 

[PATCH] D55134: [CTU] Add triple/lang mismatch handling

2018-12-03 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176417.
martong marked 13 inline comments as done.
martong added a comment.

- Address review comments


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55134/new/

https://reviews.llvm.org/D55134

Files:
  include/clang/Basic/DiagnosticCrossTUKinds.td
  include/clang/CrossTU/CrossTranslationUnit.h
  lib/CrossTU/CrossTranslationUnit.cpp
  test/Analysis/ctu-different-triples.cpp
  test/Analysis/ctu-unknown-parts-in-triples.cpp

Index: test/Analysis/ctu-unknown-parts-in-triples.cpp
===
--- /dev/null
+++ test/Analysis/ctu-unknown-parts-in-triples.cpp
@@ -0,0 +1,16 @@
+// We do not expect any error when one part of the triple is unknown, but other
+// known parts are equal.
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%t/ctudir -verify %s
+
+// expected-no-diagnostics
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: test/Analysis/ctu-different-triples.cpp
===
--- /dev/null
+++ test/Analysis/ctu-different-triples.cpp
@@ -0,0 +1,14 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_cc1 -triple powerpc64-montavista-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%t/ctudir -verify %s
+
+// We expect an error in this file, but without a location.
+// expected-error-re@./ctu-different-triples.cpp:*{{imported AST from {{.*}} had been generated for a different target, current: powerpc64-montavista-linux-gnu, imported: x86_64-pc-linux-gnu}}
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -32,6 +32,36 @@
 namespace cross_tu {
 
 namespace {
+
+// Same as Triple's equality operator, but we check a field only if that is
+// known in both instances.
+bool hasEqualKnownFields(const llvm::Triple , const llvm::Triple ) {
+  using llvm::Triple;
+  if (Lhs.getArch() != Triple::UnknownArch &&
+  Rhs.getArch() != Triple::UnknownArch && Lhs.getArch() != Rhs.getArch())
+return false;
+  if (Lhs.getSubArch() != Triple::NoSubArch &&
+  Rhs.getSubArch() != Triple::NoSubArch &&
+  Lhs.getSubArch() != Rhs.getSubArch())
+return false;
+  if (Lhs.getVendor() != Triple::UnknownVendor &&
+  Rhs.getVendor() != Triple::UnknownVendor &&
+  Lhs.getVendor() != Rhs.getVendor())
+return false;
+  if (!Lhs.isOSUnknown() && !Rhs.isOSUnknown() &&
+  Lhs.getOS() != Rhs.getOS())
+return false;
+  if (Lhs.getEnvironment() != Triple::UnknownEnvironment &&
+  Rhs.getEnvironment() != Triple::UnknownEnvironment &&
+  Lhs.getEnvironment() != Rhs.getEnvironment())
+return false;
+  if (Lhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+  Rhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+  Lhs.getObjectFormat() != Rhs.getObjectFormat())
+return false;
+  return true;
+}
+
 // FIXME: This class is will be removed after the transition to llvm::Error.
 class IndexErrorCategory : public std::error_category {
 public:
@@ -55,6 +85,10 @@
   return "Failed to load external AST source.";
 case index_error_code::failed_to_generate_usr:
   return "Failed to generate USR.";
+case index_error_code::triple_mismatch:
+  return "Triple mismatch";
+case index_error_code::lang_mismatch:
+  return "Language mismatch";
 }
 llvm_unreachable("Unrecognized index_error_code.");
   }
@@ -166,6 +200,30 @@
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
+  const auto  = Context.getTargetInfo().getTriple();
+  const auto  = Unit->getASTContext().getTargetInfo().getTriple();
+  // The imported AST had been generated for a different target.
+  // Some parts of the triple in the loaded ASTContext can be unknown while the
+  // very same parts in the target ASTContext are known. Thus we check for the
+  // known parts only.
+  if (!hasEqualKnownFields(TripleTo, TripleFrom)) {
+// TODO: Pass the SourceLocation of the CallExpression for more precise
+// diagnostics.
+

[PATCH] D55134: [CTU] Add triple/lang mismatch handling

2018-12-03 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

> Hah. Do we support CTU for other languages, like ObjC and ObjC++? Can this be 
> an issue there?

I really don't know. We never tried it, our focus is on C and C++ for now. 
Unfortunately, there is nobody with ObjC/C++ knowledge and (more importantly) 
with interest to try CTU and report any errors.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55134/new/

https://reviews.llvm.org/D55134



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


[PATCH] D55134: [CTU] Add triple/lang mismatch handling

2018-12-03 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

Thanks for the review! I have updated the patch according to your comments.




Comment at: lib/CrossTU/CrossTranslationUnit.cpp:31
 
+namespace llvm {
+// Same as Triple's equality operator, but we check a field only if that is

a_sidorin wrote:
> Why don't we place it into the anon namespace just below?
Ok, I moved it into the unnamed namespace below.



Comment at: lib/CrossTU/CrossTranslationUnit.cpp:35
+bool hasEqualKnownFields(const Triple , const Triple ) {
+  return ((Lhs.getArch() != Triple::UnknownArch &&
+   Rhs.getArch() != Triple::UnknownArch)

a_sidorin wrote:
> This has to be split, probably with early returns. Example:
> ```if (Lhs.getArch() != Triple::UnknownArch && Rhs.getArch() != 
> Triple::UnknownArch &&
>   Lhs.getArch() != Rhs.getArch()
>   return false;
> ...```
Ok, I split that up with early returns.



Comment at: lib/CrossTU/CrossTranslationUnit.cpp:59
+}
+}
+

a_sidorin wrote:
> Szelethus wrote:
> > `// end of namespace llvm`
> `// end namespace llvm` is much more common.
Moved to the unnamed namespace.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55134/new/

https://reviews.llvm.org/D55134



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


[PATCH] D44100: [ASTImporter] Reorder fields after structure import is finished

2018-12-01 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

Alexei,

I had a chance to have a quick look into this on a borrowed Mac Book. Seems 
like the assertion which was related to the revert is not existent anymore, but 
a new assertion came in. Next week I'll have time to debug that and I'll come 
back to you with what I find.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D44100/new/

https://reviews.llvm.org/D44100



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


[PATCH] D55280: [CTU] Make loadExternalAST return with non nullptr on success

2018-12-06 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

Hi Aleksey,

The first version was indeed not correct. But, I think we handle that case with 
the latest update (https://reviews.llvm.org/differential/diff/176779/).  In 
`loadExternalAST()` we have this right before the return:

  if (!Unit)
  return llvm::make_error(
  index_error_code::failed_to_get_external_ast);
  return Unit;

So we will never return with a nullptr value in the `Expected`.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55280/new/

https://reviews.llvm.org/D55280



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


[PATCH] D53655: [ASTImporter] Fix redecl chain of classes and class templates

2018-12-10 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

@rsmith Please raise any objections until Dec 14 (or if this deadline is too 
strict). I'd like to commit this next week latest so it can get in still this 
year.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53655/new/

https://reviews.llvm.org/D53655



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


[PATCH] D44100: [ASTImporter] Reorder fields after structure import is finished

2018-12-10 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

@a_sidorin

The below diff on top of your patch successfully handles the failure with the 
`TestCModules.py` LLDB testcase:

  diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
  index 05fec7f943..e6fb590025 100644
  --- a/lib/AST/ASTImporter.cpp
  +++ b/lib/AST/ASTImporter.cpp
  @@ -1695,15 +1695,22 @@ ASTNodeImporter::ImportDeclContext(DeclContext 
*FromDC, bool ForceImport) {
 // LoadFieldsFromExternalStorage().
 auto ImportedDC = import(cast(FromDC));
 assert(ImportedDC);
  -  auto *ToRD = cast(*ImportedDC);
  +  RecordDecl *ToRD = nullptr;
 for (auto *D : FromRD->decls()) {
   if (isa(D) || isa(D)) {
 Decl *ToD = Importer.GetAlreadyImportedOrNull(D);
  -  assert(ToRD == ToD->getDeclContext() && ToRD->containsDecl(ToD));
  -  ToRD->removeDecl(ToD);
  +  if (!ToRD)
  +ToRD = cast(ToD->getDeclContext());
  +  else
  +assert(ToRD == ToD->getDeclContext());
  +  if(ToRD->containsDecl(ToD))
  +ToRD->removeDecl(ToD);
   }
 }
  
  +  if (!ToRD)
  +return Error::success();
  +
 if (!ToRD->hasExternalLexicalStorage())
   assert(ToRD->field_empty());


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D44100/new/

https://reviews.llvm.org/D44100



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


[PATCH] D44100: [ASTImporter] Reorder fields after structure import is finished

2018-12-10 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

There is another failure on macOS, which is not there on Linux. This is present 
with the 174545 patch id (even before applying my fix for TestCModules).

  $ ninja check-clang-astmerge
  
  Testing Time: 0.63s
  
  Failing Tests (4):
  Clang :: ASTMerge/class-template-partial-spec/test.cpp
  Clang :: ASTMerge/class-template/test.cpp
  Clang :: ASTMerge/class/test.cpp
  Clang :: ASTMerge/struct/test.c
  
Expected Passes: 22
Expected Failures  : 1
Unexpected Failures: 4
  FAILED: tools/clang/test/CMakeFiles/check-clang-astmerge

Now I am diving into this.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D44100/new/

https://reviews.llvm.org/D44100



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


[PATCH] D53708: [ASTImporter] Add importer specific lookup

2018-11-30 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176100.
martong marked 3 inline comments as done.
martong added a comment.

- Address Alexei's comments
- Rename FindDeclsInToCtx to findDeclsInToCtx
- Remove superfluous spaces from stringliterals
- Remove unused header
- Remove empty test
- Return nullptr and FindInDeclListOfDC -> findInDeclListOfDC
- Use SmallSetVector instead of SmallPtrSet


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53708/new/

https://reviews.llvm.org/D53708

Files:
  include/clang/AST/ASTImporter.h
  include/clang/AST/ASTImporterLookupTable.h
  include/clang/CrossTU/CrossTranslationUnit.h
  lib/AST/ASTImporter.cpp
  lib/AST/ASTImporterLookupTable.cpp
  lib/AST/CMakeLists.txt
  lib/CrossTU/CrossTranslationUnit.cpp
  lib/Frontend/ASTMerge.cpp
  unittests/AST/ASTImporterTest.cpp

Index: unittests/AST/ASTImporterTest.cpp
===
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -14,6 +14,7 @@
 #include "MatchVerifier.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTImporter.h"
+#include "clang/AST/ASTImporterLookupTable.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/Tooling.h"
@@ -307,24 +308,27 @@
   Unit->enableSourceFileDiagnostics();
 }
 
-void lazyInitImporter(ASTUnit *ToAST) {
+void lazyInitImporter(ASTImporterLookupTable , ASTUnit *ToAST) {
   assert(ToAST);
   if (!Importer) {
-Importer.reset(new ASTImporter(
-ToAST->getASTContext(), ToAST->getFileManager(),
-Unit->getASTContext(), Unit->getFileManager(), false));
+Importer.reset(
+new ASTImporter(ToAST->getASTContext(), ToAST->getFileManager(),
+Unit->getASTContext(), Unit->getFileManager(),
+false, ));
   }
   assert(>getASTContext() == >getToContext());
   createVirtualFileIfNeeded(ToAST, FileName, Code);
 }
 
-Decl *import(ASTUnit *ToAST, Decl *FromDecl) {
-  lazyInitImporter(ToAST);
+Decl *import(ASTImporterLookupTable , ASTUnit *ToAST,
+ Decl *FromDecl) {
+  lazyInitImporter(LookupTable, ToAST);
   return Importer->Import(FromDecl);
- }
+}
 
-QualType import(ASTUnit *ToAST, QualType FromType) {
-  lazyInitImporter(ToAST);
+QualType import(ASTImporterLookupTable , ASTUnit *ToAST,
+QualType FromType) {
+  lazyInitImporter(LookupTable, ToAST);
   return Importer->Import(FromType);
 }
   };
@@ -338,13 +342,23 @@
   // vector is expanding, with the list we won't have these issues.
   std::list FromTUs;
 
-  void lazyInitToAST(Language ToLang) {
+  // Initialize the lookup table if not initialized already.
+  void lazyInitLookupTable(TranslationUnitDecl *ToTU) {
+assert(ToTU);
+if (!LookupTablePtr)
+  LookupTablePtr = llvm::make_unique(*ToTU);
+  }
+
+  void lazyInitToAST(Language ToLang, StringRef ToSrcCode, StringRef FileName) {
 if (ToAST)
   return;
 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
+// Source code must be a valid live buffer through the tests lifetime.
+ToCode = ToSrcCode;
 // Build the AST from an empty file.
-ToAST = tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
+ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, FileName);
 ToAST->enableSourceFileDiagnostics();
+lazyInitLookupTable(ToAST->getASTContext().getTranslationUnitDecl());
   }
 
   TU *findFromTU(Decl *From) {
@@ -358,6 +372,10 @@
 return &*It;
   }
 
+protected:
+
+  std::unique_ptr LookupTablePtr;
+
 public:
   // We may have several From context but only one To context.
   std::unique_ptr ToAST;
@@ -374,26 +392,23 @@
 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
 TU  = FromTUs.back();
 
-ToCode = ToSrcCode;
 assert(!ToAST);
-ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
-ToAST->enableSourceFileDiagnostics();
+lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
 
 ASTContext  = FromTU.Unit->getASTContext();
 
-createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
-
 IdentifierInfo *ImportedII = (Identifier);
 assert(ImportedII && "Declaration with the given identifier "
  "should be specified in test!");
 DeclarationName ImportDeclName(ImportedII);
-SmallVector FoundDecls;
+SmallVector FoundDecls;
 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
   FoundDecls);
 
 assert(FoundDecls.size() == 1);
 
-Decl *Imported = FromTU.import(ToAST.get(), FoundDecls.front());
+Decl *Imported =
+FromTU.import(*LookupTablePtr, ToAST.get(), FoundDecls.front());
 
 assert(Imported);
 return 

[PATCH] D53708: [ASTImporter] Add importer specific lookup

2018-11-30 Thread Gabor Marton via Phabricator via cfe-commits
martong marked 8 inline comments as done.
martong added inline comments.



Comment at: lib/AST/ASTImporter.cpp:7658
+ASTImporter::FoundDeclsTy
+ASTImporter::FindDeclsInToCtx(DeclContext *DC, DeclarationName Name) {
+  // We search in the redecl context because of transparent contexts.

a_sidorin wrote:
> Naming conventions require method names to start with a small letter.
Okay, I changed it. Unfortunately `ASTImporter` does not really follow the 
conventions. Most of the functions start with a capital letter, and some with a 
small case.
E.g.:
```
/// Retrieve the file manager that AST nodes are being imported from.
FileManager () const { return FromFileManager; }

/// Report a diagnostic in the "to" context.
DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID);

```



Comment at: tools/clang-import-test/clang-import-test.cpp:12
 #include "clang/AST/ASTImporter.h"
+#include "clang/AST/ASTImporterLookupTable.h"
 #include "clang/AST/DeclObjC.h"

a_sidorin wrote:
> It looks like the only change done to this file is including a header. Are 
> there any related changes that should be added?
Thank you, this is a good catch, I removed it.



Comment at: unittests/AST/ASTImporterTest.cpp:3845
+  ASTImporterLookupTable LT(*ToTU);
+}
+

a_sidorin wrote:
> martong wrote:
> > a_sidorin wrote:
> > > Could you please explain what does this test do?
> > Well, it makes sure that we can build a lookup table for an empty file 
> > without any *assertion*. We may have an assertion in the ctor during 
> > traversing the AST. I consider this the most basic use case as it tests 
> > only the constructor.
> > However, if you find it weird I can remove it.
> Yes, I think it's better to remove it or check some invariants of an empty 
> lookup table.
Ok, I removed it.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53708/new/

https://reviews.llvm.org/D53708



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


[PATCH] D53708: [ASTImporter] Add importer specific lookup

2018-11-30 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

Hey Alexei,

Thank you again for your comments. I changed to code accordingly.

Also, I recognized that we should use a `SmallSetVector` instead of a 
`SmallPtrSet`, because the latter results unpredictable iteration (pointers may 
have different values with each run). Though `SmallPtrSet` is more powerful 
than `SmallSetVector` it makes it really hard to debug false positive ODR 
warnings from the ASTImporter, because the warning may appear in one run but 
may not appear in the subsequent run. We need an iteration order in the order 
of insertions and that is produced by `SmallSetVector`.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53708/new/

https://reviews.llvm.org/D53708



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


[PATCH] D55134: [CTU] Add triple/lang mismatch handling

2018-12-04 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 176686.
martong marked an inline comment as done.
martong added a comment.

- Add a case to emitCrossTUDiagnostics


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55134/new/

https://reviews.llvm.org/D55134

Files:
  include/clang/Basic/DiagnosticCrossTUKinds.td
  include/clang/Basic/DiagnosticGroups.td
  include/clang/CrossTU/CrossTranslationUnit.h
  lib/CrossTU/CrossTranslationUnit.cpp
  test/Analysis/ctu-different-triples.cpp
  test/Analysis/ctu-unknown-parts-in-triples.cpp

Index: test/Analysis/ctu-unknown-parts-in-triples.cpp
===
--- /dev/null
+++ test/Analysis/ctu-unknown-parts-in-triples.cpp
@@ -0,0 +1,22 @@
+// We do not expect any error when one part of the triple is unknown, but other
+// known parts are equal.
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -analyze \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -Werror=ctu \
+// RUN:   -verify %s
+
+// expected-no-diagnostics
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: test/Analysis/ctu-different-triples.cpp
===
--- /dev/null
+++ test/Analysis/ctu-different-triples.cpp
@@ -0,0 +1,20 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %t/ctudir/externalFnMap.txt
+// RUN: %clang_cc1 -triple powerpc64-montavista-linux-gnu -fsyntax-only \
+// RUN:   -analyze -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN:   -analyzer-config ctu-dir=%t/ctudir \
+// RUN:   -Werror=ctu \
+// RUN:   -verify %s
+
+// We expect an error in this file, but without a location.
+// expected-error-re@./ctu-different-triples.cpp:*{{imported AST from {{.*}} had been generated for a different target, current: powerpc64-montavista-linux-gnu, imported: x86_64-pc-linux-gnu}}
+
+int f(int);
+
+int main() {
+  return f(5);
+}
Index: lib/CrossTU/CrossTranslationUnit.cpp
===
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -32,6 +32,36 @@
 namespace cross_tu {
 
 namespace {
+
+// Same as Triple's equality operator, but we check a field only if that is
+// known in both instances.
+bool hasEqualKnownFields(const llvm::Triple , const llvm::Triple ) {
+  using llvm::Triple;
+  if (Lhs.getArch() != Triple::UnknownArch &&
+  Rhs.getArch() != Triple::UnknownArch && Lhs.getArch() != Rhs.getArch())
+return false;
+  if (Lhs.getSubArch() != Triple::NoSubArch &&
+  Rhs.getSubArch() != Triple::NoSubArch &&
+  Lhs.getSubArch() != Rhs.getSubArch())
+return false;
+  if (Lhs.getVendor() != Triple::UnknownVendor &&
+  Rhs.getVendor() != Triple::UnknownVendor &&
+  Lhs.getVendor() != Rhs.getVendor())
+return false;
+  if (!Lhs.isOSUnknown() && !Rhs.isOSUnknown() &&
+  Lhs.getOS() != Rhs.getOS())
+return false;
+  if (Lhs.getEnvironment() != Triple::UnknownEnvironment &&
+  Rhs.getEnvironment() != Triple::UnknownEnvironment &&
+  Lhs.getEnvironment() != Rhs.getEnvironment())
+return false;
+  if (Lhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+  Rhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+  Lhs.getObjectFormat() != Rhs.getObjectFormat())
+return false;
+  return true;
+}
+
 // FIXME: This class is will be removed after the transition to llvm::Error.
 class IndexErrorCategory : public std::error_category {
 public:
@@ -55,6 +85,10 @@
   return "Failed to load external AST source.";
 case index_error_code::failed_to_generate_usr:
   return "Failed to generate USR.";
+case index_error_code::triple_mismatch:
+  return "Triple mismatch";
+case index_error_code::lang_mismatch:
+  return "Language mismatch";
 }
 llvm_unreachable("Unrecognized index_error_code.");
   }
@@ -166,6 +200,31 @@
   assert(>getFileManager() ==
  >getASTContext().getSourceManager().getFileManager());
 
+  const llvm::Triple  = Context.getTargetInfo().getTriple();
+  const llvm::Triple  =
+  Unit->getASTContext().getTargetInfo().getTriple();
+  // The imported AST had been generated for a different target.
+  // Some parts of the triple in the loaded ASTContext can be unknown while the
+  // very same parts in the target ASTContext 

[PATCH] D44100: [ASTImporter] Reorder fields after structure import is finished

2018-12-06 Thread Gabor Marton via Phabricator via cfe-commits
martong added a comment.

Hey Alexey,

Here is what I found so far:
The new assertion is this:

  Assertion failed: (ToRD == ToD->getDeclContext() && ToRD->containsDecl(ToD)), 
function ImportDeclContext

ToRD looks like this in code:

  typedef struct __sFILE {
 // several fields here ...
  } FILE;

And the AST:

  CXXRecordDecl 0x7f87ce97d488 
 col:16 struct __sFILE definition
  |-DefinitionData pass_in_registers aggregate standard_layout 
trivially_copyable pod trivial literal
  | |-DefaultConstructor exists trivial needs_implicit
  | |-CopyConstructor simple trivial has_const_param needs_implicit 
implicit_has_const_param
  | |-MoveConstructor exists simple trivial needs_implicit
  | |-CopyAssignment trivial has_const_param needs_implicit 
implicit_has_const_param
  | |-MoveAssignment exists simple trivial needs_implicit
  | `-Destructor simple irrelevant trivial needs_implicit
  |-CXXRecordDecl 0x7f87d1886000  col:16 implicit struct __sFILE
  | `-
  `-

I dug deeper and this is because `ToRD` is not equal with 
`ToD->getDeclContext()`.
However, if I load the fields of `ToRD` and then dump it seems to be 
structurally equivalent with `ToD->getDeclContext()`.
Both `ToRD` and `ToD->getDeclContext()` are part of a Decl chain with one 
element, this is true for `FromRD` and `D->getDeclContext()`. So I suspect some 
sort of lookup problem here: first we import the declContext during the import 
of a field, then when we do `auto ImportedDC = import(cast(FromDC));` 
where we fail to find the first imported DeclContext. I suspect that this is 
because typedef hides the real struct, I mean `__sFILE` seems to be not 
find-able by normal C lookup (ie. it is hidden).

Here is one workaround (I did not try it yet):
We could lazy initialize `ToRD` inside the for loop to be equal to the first 
'ToD`'s decl context.

  RecordDecl *ToRD = nullptr;
  for (auto *D : FromRD->decls()) {
if (isa(D) || isa(D)) {
  Decl *ToD = Importer.GetAlreadyImportedOrNull(D);
  if (!ToRD)
  ToRD = ToD->getDeclContext();
  ToRD->removeDecl(ToD);
}
  }

I am afraid I can continue with the debug only next week.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D44100/new/

https://reviews.llvm.org/D44100



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


[PATCH] D53655: [ASTImporter] Fix redecl chain of classes and class templates

2018-11-23 Thread Gabor Marton via Phabricator via cfe-commits
martong updated this revision to Diff 175127.
martong added a comment.

- Use MostRecentDecl when setting PrevDecl


Repository:
  rC Clang

https://reviews.llvm.org/D53655

Files:
  include/clang/AST/DeclContextInternals.h
  include/clang/ASTMatchers/ASTMatchers.h
  lib/AST/ASTImporter.cpp
  lib/AST/DeclBase.cpp
  lib/ASTMatchers/ASTMatchersInternal.cpp
  unittests/AST/ASTImporterTest.cpp
  unittests/AST/StructuralEquivalenceTest.cpp

Index: unittests/AST/StructuralEquivalenceTest.cpp
===
--- unittests/AST/StructuralEquivalenceTest.cpp
+++ unittests/AST/StructuralEquivalenceTest.cpp
@@ -597,6 +597,77 @@
   EXPECT_FALSE(testStructuralMatch(R0, R1));
 }
 
+TEST_F(StructuralEquivalenceRecordTest, AnonymousRecordsShouldBeInequivalent) {
+  auto t = makeTuDecls(
+  R"(
+  struct X {
+struct {
+  int a;
+};
+struct {
+  int b;
+};
+  };
+  )",
+  "", Lang_C);
+  auto *TU = get<0>(t);
+  auto *A = FirstDeclMatcher().match(
+  TU, indirectFieldDecl(hasName("a")));
+  auto *FA = cast(A->chain().front());
+  RecordDecl *RA = cast(FA->getType().getTypePtr())->getDecl();
+  auto *B = FirstDeclMatcher().match(
+  TU, indirectFieldDecl(hasName("b")));
+  auto *FB = cast(B->chain().front());
+  RecordDecl *RB = cast(FB->getType().getTypePtr())->getDecl();
+
+  ASSERT_NE(RA, RB);
+  EXPECT_TRUE(testStructuralMatch(RA, RA));
+  EXPECT_TRUE(testStructuralMatch(RB, RB));
+  EXPECT_FALSE(testStructuralMatch(RA, RB));
+}
+
+TEST_F(StructuralEquivalenceRecordTest,
+   RecordsAreInequivalentIfOrderOfAnonRecordsIsDifferent) {
+  auto t = makeTuDecls(
+  R"(
+  struct X {
+struct { int a; };
+struct { int b; };
+  };
+  )",
+  R"(
+  struct X { // The order is reversed.
+struct { int b; };
+struct { int a; };
+  };
+  )",
+  Lang_C);
+
+  auto *TU = get<0>(t);
+  auto *A = FirstDeclMatcher().match(
+  TU, indirectFieldDecl(hasName("a")));
+  auto *FA = cast(A->chain().front());
+  RecordDecl *RA = cast(FA->getType().getTypePtr())->getDecl();
+
+  auto *TU1 = get<1>(t);
+  auto *A1 = FirstDeclMatcher().match(
+  TU1, indirectFieldDecl(hasName("a")));
+  auto *FA1 = cast(A1->chain().front());
+  RecordDecl *RA1 = cast(FA1->getType().getTypePtr())->getDecl();
+
+  RecordDecl *X =
+  FirstDeclMatcher().match(TU, recordDecl(hasName("X")));
+  RecordDecl *X1 =
+  FirstDeclMatcher().match(TU1, recordDecl(hasName("X")));
+  ASSERT_NE(X, X1);
+  EXPECT_FALSE(testStructuralMatch(X, X1));
+
+  ASSERT_NE(RA, RA1);
+  EXPECT_TRUE(testStructuralMatch(RA, RA));
+  EXPECT_TRUE(testStructuralMatch(RA1, RA1));
+  EXPECT_FALSE(testStructuralMatch(RA1, RA));
+}
+
 TEST_F(StructuralEquivalenceRecordTest,
UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) {
   auto Code =
Index: unittests/AST/ASTImporterTest.cpp
===
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -11,9 +11,10 @@
 //
 //===--===//
 
+#include "clang/AST/ASTImporter.h"
 #include "MatchVerifier.h"
 #include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTImporter.h"
+#include "clang/AST/DeclContextInternals.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/Tooling.h"
@@ -1808,6 +1809,65 @@
   EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
 }
 
+TEST_P(ASTImporterTestBase, AnonymousRecords) {
+  auto *Code =
+  R"(
+  struct X {
+struct { int a; };
+struct { int b; };
+  };
+  )";
+  Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
+
+  Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
+
+  auto *X0 =
+  FirstDeclMatcher().match(FromTU0, recordDecl(hasName("X")));
+  auto *X1 =
+  FirstDeclMatcher().match(FromTU1, recordDecl(hasName("X")));
+  Import(X0, Lang_C);
+  Import(X1, Lang_C);
+
+  auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+  // We expect no (ODR) warning during the import.
+  EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
+  EXPECT_EQ(1u,
+DeclCounter().match(ToTU, recordDecl(hasName("X";
+}
+
+TEST_P(ASTImporterTestBase, AnonymousRecordsReversed) {
+  Decl *FromTU0 = getTuDecl(
+  R"(
+  struct X {
+struct { int a; };
+struct { int b; };
+  };
+  )",
+  Lang_C, "input0.c");
+
+  Decl *FromTU1 = getTuDecl(
+  R"(
+  struct X { // reversed order
+struct { int b; };
+struct { int a; };
+  };
+  )",
+  Lang_C, "input1.c");
+
+  auto *X0 =
+  FirstDeclMatcher().match(FromTU0, recordDecl(hasName("X")));
+  auto *X1 =
+  FirstDeclMatcher().match(FromTU1, recordDecl(hasName("X")));
+  Import(X0, Lang_C);
+  

<    1   2   3   4   5   6   7   8   9   10   >