]> granicus.if.org Git - clang/commitdiff
[ASTmporter] SourceRange-free function parameter checking for declarations
authorGabor Marton <martongabesz@gmail.com>
Mon, 6 Aug 2018 14:38:37 +0000 (14:38 +0000)
committerGabor Marton <martongabesz@gmail.com>
Mon, 6 Aug 2018 14:38:37 +0000 (14:38 +0000)
Summary: The previous code which avoided infinite recursion (because of reparsing declarations in function parameter lists) contained SourceRange dependent code which had some problems when parameter types were coming from macros. The new solution is not using macros and therefore much safer. A couple of importer problems are fixed in redis and tmux by this fix. Various unittests are included.

Reviewers: a.sidorin, r.stahl, a_sidorin

Reviewed By: a_sidorin

Subscribers: cfe-commits, dkrupp, balazske, martong

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

Patch by Zoltan Gera!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@339018 91177308-0d34-0410-b5e6-96231b3b80d8

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

index b360b3910636492c75c0442ba73c1b7f7cc6c798..38ad4e28931427d1e0044bccf0d9c5cd1aab9ffb 100644 (file)
@@ -1147,15 +1147,21 @@ bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC,
   FunctionDecl *FunDecl;
   if (isa<RecordDecl>(D) && (FunDecl = dyn_cast<FunctionDecl>(OrigDC)) &&
       FunDecl->hasBody()) {
-    SourceRange RecR = D->getSourceRange();
-    SourceRange BodyR = FunDecl->getBody()->getSourceRange();
-    // If RecordDecl is not in Body (it is a param), we bail out.
-    if (RecR.isValid() && BodyR.isValid() &&
-        (RecR.getBegin() < BodyR.getBegin() ||
-         BodyR.getEnd() < RecR.getEnd())) {
-      Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
-          << D->getDeclKindName();
-      return true;
+    auto getLeafPointeeType = [](const Type *T) {
+      while (T->isPointerType() || T->isArrayType()) {
+        T = T->getPointeeOrArrayElementType();
+      }
+      return T;
+    };
+    for (const ParmVarDecl *P : FunDecl->parameters()) {
+      const Type *LeafT =
+          getLeafPointeeType(P->getType().getCanonicalType().getTypePtr());
+      auto *RT = dyn_cast<RecordType>(LeafT);
+      if (RT && RT->getDecl() == D) {
+        Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
+            << D->getDeclKindName();
+        return true;
+      }
     }
   }
 
index 21b76173c1057f53f718170152a219498ec1c489..04006a0bea34d19aacbddc4fe18962afc5cd024f 100644 (file)
@@ -989,7 +989,7 @@ TEST_P(ASTImporterTestBase, ImportRecordTypeInFunc) {
                            "  return 0;"
                            "}",
                            Lang_C, "input.c");
-  auto FromVar =
+  auto *FromVar =
       FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
   ASSERT_TRUE(FromVar);
   auto ToType =
@@ -999,12 +999,41 @@ TEST_P(ASTImporterTestBase, ImportRecordTypeInFunc) {
 
 TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParams) {
   // This construct is not supported by ASTImporter.
-  Decl *FromTU =
-      getTuDecl("int declToImport(struct data_t{int a;int b;} *d){ return 0; }",
-                Lang_C, "input.c");
-  auto From = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
+  Decl *FromTU = getTuDecl(
+      "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
+      Lang_C, "input.c");
+  auto *From = FirstDeclMatcher<FunctionDecl>().match(
+      FromTU, functionDecl(hasName("declToImport")));
+  ASSERT_TRUE(From);
+  auto *To = Import(From, Lang_C);
+  EXPECT_EQ(To, nullptr);
+}
+
+TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncFromMacro) {
+  Decl *FromTU = getTuDecl(
+      "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
+      "int declToImport(){ return NONAME_SIZEOF(int); }",
+      Lang_C, "input.c");
+  auto *From = FirstDeclMatcher<FunctionDecl>().match(
+      FromTU, functionDecl(hasName("declToImport")));
+  ASSERT_TRUE(From);
+  auto *To = Import(From, Lang_C);
+  ASSERT_TRUE(To);
+  EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
+      To, functionDecl(hasName("declToImport"),
+                       hasDescendant(unaryExprOrTypeTraitExpr()))));
+}
+
+TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParamsFromMacro) {
+  // This construct is not supported by ASTImporter.
+  Decl *FromTU = getTuDecl(
+      "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
+      "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
+      Lang_C, "input.c");
+  auto *From = FirstDeclMatcher<FunctionDecl>().match(
+      FromTU, functionDecl(hasName("declToImport")));
   ASSERT_TRUE(From);
-  auto To = Import(From, Lang_C);
+  auto *To = Import(From, Lang_C);
   EXPECT_EQ(To, nullptr);
 }