tmroeder created this revision. Herald added a reviewer: shafik. Herald added subscribers: cfe-commits, jdoerfert. Herald added a project: clang.
This allows ASTs to be merged when they contain ChooseExpr (the GNU __builtin_choose_expr construction). This is needed, for example, for cross-CTU analysis of C code that makes use of __builtin_choose_expr. The node is already supported in the AST, but it didn't have a matcher in ASTMatchers. So, this change adds the matcher and adds support to ASTImporter. Repository: rC Clang https://reviews.llvm.org/D58292 Files: include/clang/ASTMatchers/ASTMatchers.h lib/AST/ASTImporter.cpp lib/ASTMatchers/ASTMatchersInternal.cpp test/ASTMerge/choose-expr/Inputs/choose1.c test/ASTMerge/choose-expr/Inputs/choose2.c test/ASTMerge/choose-expr/test.c unittests/AST/ASTImporterTest.cpp
Index: unittests/AST/ASTImporterTest.cpp =================================================================== --- unittests/AST/ASTImporterTest.cpp +++ unittests/AST/ASTImporterTest.cpp @@ -563,6 +563,15 @@ stringLiteral(hasType(asString("const char [7]")))))); } +TEST_P(ImportExpr, ImportChooseExpr) { + MatchVerifier<Decl> Verifier; + + testImport( + "void declToImport() { __builtin_choose_expr(1, 2, 3); }", + Lang_C, "", Lang_C, Verifier, + functionDecl(hasDescendant(chooseExpr()))); +} + TEST_P(ImportExpr, ImportGNUNullExpr) { MatchVerifier<Decl> Verifier; testImport( @@ -1082,6 +1091,38 @@ EXPECT_EQ(To, nullptr); } +TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) { + MatchVerifier<Decl> Verifier; + + // The macro in this TuDecl violates standard rules of macros (like not + // using a variable more than once), but it's only used to test a realistic + // __builtin_choose_expr construction. + Decl *FromTU = getTuDecl( + R"( + #define abs_int(x) __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof(x), unsigned int), \ + x, \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof(x), int), \ + x < 0 ? -x : x, \ + (void)0)) + void declToImport() { + int x = -10; + int abs_x = abs_int(x); + (void)abs_x; + } + )", + 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(chooseExpr(hasDescendant(chooseExpr())))))); +} + const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr> cxxPseudoDestructorExpr; Index: test/ASTMerge/choose-expr/test.c =================================================================== --- /dev/null +++ test/ASTMerge/choose-expr/test.c @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/choose1.c +// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/choose2.c +// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 Index: test/ASTMerge/choose-expr/Inputs/choose2.c =================================================================== --- /dev/null +++ test/ASTMerge/choose-expr/Inputs/choose2.c @@ -0,0 +1,12 @@ +#define abs_int(x) __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof(x), unsigned int), \ + x, \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof(x), int), \ + x < 0 ? -x : x, \ + (void)0)) +void declToImport() { + int x = -10; + int abs_x = abs_int(x); + (void)abs_x; +} Index: test/ASTMerge/choose-expr/Inputs/choose1.c =================================================================== --- /dev/null +++ test/ASTMerge/choose-expr/Inputs/choose1.c @@ -0,0 +1,12 @@ +#define abs_int(x) __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof(x), unsigned int), \ + x, \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof(x), int), \ + x < 0 ? -x : x, \ + (void)0)) +void declToImport() { + int x = -10; + int abs_x = abs_int(x); + (void)abs_x; +} Index: lib/ASTMatchers/ASTMatchersInternal.cpp =================================================================== --- lib/ASTMatchers/ASTMatchersInternal.cpp +++ lib/ASTMatchers/ASTMatchersInternal.cpp @@ -727,6 +727,7 @@ compoundLiteralExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNullPtrLiteralExpr> cxxNullPtrLiteralExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, ChooseExpr> chooseExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr> gnuNullExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr; Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -552,6 +552,7 @@ // Importing expressions ExpectedStmt VisitExpr(Expr *E); ExpectedStmt VisitVAArgExpr(VAArgExpr *E); + ExpectedStmt VisitChooseExpr(ChooseExpr *E); ExpectedStmt VisitGNUNullExpr(GNUNullExpr *E); ExpectedStmt VisitPredefinedExpr(PredefinedExpr *E); ExpectedStmt VisitDeclRefExpr(DeclRefExpr *E); @@ -6135,6 +6136,35 @@ E->isMicrosoftABI()); } +ExpectedStmt ASTNodeImporter::VisitChooseExpr(ChooseExpr *E) { + auto Imp = importSeq(E->getCond(), E->getLHS(), E->getRHS(), + E->getBuiltinLoc(), E->getRParenLoc(), E->getType()); + if (!Imp) + return Imp.takeError(); + + Expr *ToCond; + Expr *ToLHS; + Expr *ToRHS; + SourceLocation ToBuiltinLoc, ToRParenLoc; + QualType ToType; + std::tie(ToCond, ToLHS, ToRHS, ToBuiltinLoc, ToRParenLoc, ToType) = *Imp; + + ExprValueKind VK = E->getValueKind(); + ExprObjectKind OK = E->getObjectKind(); + + bool TypeDependent = ToCond->isTypeDependent(); + bool ValueDependent = ToCond->isValueDependent(); + + // The value of CondIsTrue only matters if the value is not + // condition-dependent. + bool CondIsTrue = false; + if (!E->isConditionDependent()) + CondIsTrue = E->isConditionTrue(); + + return new (Importer.getToContext()) + ChooseExpr(ToBuiltinLoc, ToCond, ToLHS, ToRHS, ToType, VK, OK, + ToRParenLoc, CondIsTrue, TypeDependent, ValueDependent); +} ExpectedStmt ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) { ExpectedType TypeOrErr = import(E->getType()); Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -2158,6 +2158,10 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNullPtrLiteralExpr> cxxNullPtrLiteralExpr; +/// Matches GNU __builtin_choose_expr. +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ChooseExpr> + chooseExpr; + /// Matches GNU __null expression. extern const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr> gnuNullExpr;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits