Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -788,6 +788,11 @@ +
Matches GNU __builtin_choose_expr. +
Matches compound (i.e. non-scalar) literals Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -2158,6 +2158,10 @@ extern const internal::VariadicDynCastAllOfMatchercxxNullPtrLiteralExpr; +/// Matches GNU __builtin_choose_expr. +extern const internal::VariadicDynCastAllOfMatcher + chooseExpr; + /// Matches GNU __null expression. extern const internal::VariadicDynCastAllOfMatcher gnuNullExpr; 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,33 @@ 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 = E->isConditionDependent() && 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: lib/ASTMatchers/ASTMatchersInternal.cpp =================================================================== --- lib/ASTMatchers/ASTMatchersInternal.cpp +++ lib/ASTMatchers/ASTMatchersInternal.cpp @@ -727,6 +727,7 @@ compoundLiteralExpr; const internal::VariadicDynCastAllOfMatcher cxxNullPtrLiteralExpr; +const internal::VariadicDynCastAllOfMatcher chooseExpr; const internal::VariadicDynCastAllOfMatcher gnuNullExpr; const internal::VariadicDynCastAllOfMatcher atomicExpr; const internal::VariadicDynCastAllOfMatcher stmtExpr; Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -147,6 +147,7 @@ REGISTER_MATCHER(caseStmt); REGISTER_MATCHER(castExpr); REGISTER_MATCHER(characterLiteral); + REGISTER_MATCHER(chooseExpr); REGISTER_MATCHER(classTemplateDecl); REGISTER_MATCHER(classTemplateSpecializationDecl); REGISTER_MATCHER(complexType); Index: test/ASTMerge/choose-expr/Inputs/choose.c =================================================================== --- /dev/null +++ test/ASTMerge/choose-expr/Inputs/choose.c @@ -0,0 +1,2 @@ +_Static_assert(__builtin_choose_expr(1, 1, 0), "Incorrect semantics of __builtin_choose_expr"); +_Static_assert(__builtin_choose_expr(0, 0, 1), "Incorrect semantics of __builtin_choose_expr"); Index: test/ASTMerge/choose-expr/test.c =================================================================== --- /dev/null +++ test/ASTMerge/choose-expr/test.c @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -std=c11 -emit-pch -o %t.ast %S/Inputs/choose.c +// RUN: %clang_cc1 -std=c11 -ast-merge %t.ast -fsyntax-only -verify %s +// expected-no-diagnostics + 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 Verifier; + + testImport( + "void declToImport() { __builtin_choose_expr(1, 2, 3); }", + Lang_C, "", Lang_C, Verifier, + functionDecl(hasDescendant(chooseExpr()))); +} + TEST_P(ImportExpr, ImportGNUNullExpr) { MatchVerifier Verifier; testImport( Index: unittests/ASTMatchers/ASTMatchersNodeTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -754,6 +754,11 @@ EXPECT_TRUE(matches("int* i = nullptr;", cxxNullPtrLiteralExpr())); } +TEST(Matcher, ChooseExpr) { + EXPECT_TRUE(matchesC("void f() { (void)__builtin_choose_expr(1, 2, 3); }", + chooseExpr())); +} + TEST(Matcher, GNUNullExpr) { EXPECT_TRUE(matches("int* i = __null;", gnuNullExpr())); }