diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 08e34fdf2aa2f..eb917ceecf994 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -1564,6 +1564,9 @@ class FixedPointLiteral : public Expr, public APIntStorage { /// Returns an empty fixed-point literal. static FixedPointLiteral *Create(const ASTContext &C, EmptyShell Empty); + /// Returns an internal integer representation of the literal. + llvm::APInt getValue() const { return APIntStorage::getValue(); } + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } SourceLocation getEndLoc() const LLVM_READONLY { return Loc; } diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index 55a925bf86909..c1130ff70cf5c 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -1733,9 +1733,10 @@ class ForEachDescendantMatcher : public MatcherInterface { template class ValueEqualsMatcher : public SingleNodeMatcherInterface { static_assert(std::is_base_of::value || - std::is_base_of::value || - std::is_base_of::value || - std::is_base_of::value, + std::is_base_of::value || + std::is_base_of::value || + std::is_base_of::value || + std::is_base_of::value, "the node must have a getValue method"); public: diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index 680e21840b7d3..07450a0c59ec6 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -1017,6 +1017,67 @@ TEST_P(ASTMatchersTest, FloatLiteral) { notMatches("double i = 5.0;", floatLiteral(equals(llvm::APFloat(6.0))))); } +TEST_P(ASTMatchersTest, FixedPointLiterals) { + StatementMatcher HasFixedPointLiteral = fixedPointLiteral(); + EXPECT_TRUE(matchesWithFixedpoint("_Fract i = 0.25r;", HasFixedPointLiteral)); + EXPECT_TRUE( + matchesWithFixedpoint("_Fract i = 0.25hr;", HasFixedPointLiteral)); + EXPECT_TRUE( + matchesWithFixedpoint("_Fract i = 0.25uhr;", HasFixedPointLiteral)); + EXPECT_TRUE( + matchesWithFixedpoint("_Fract i = 0.25ur;", HasFixedPointLiteral)); + EXPECT_TRUE( + matchesWithFixedpoint("_Fract i = 0.25lr;", HasFixedPointLiteral)); + EXPECT_TRUE( + matchesWithFixedpoint("_Fract i = 0.25ulr;", HasFixedPointLiteral)); + EXPECT_TRUE(matchesWithFixedpoint("_Accum i = 1.25k;", HasFixedPointLiteral)); + EXPECT_TRUE( + matchesWithFixedpoint("_Accum i = 1.25hk;", HasFixedPointLiteral)); + EXPECT_TRUE( + matchesWithFixedpoint("_Accum i = 1.25uhk;", HasFixedPointLiteral)); + EXPECT_TRUE( + matchesWithFixedpoint("_Accum i = 1.25uk;", HasFixedPointLiteral)); + EXPECT_TRUE( + matchesWithFixedpoint("_Accum i = 1.25lk;", HasFixedPointLiteral)); + EXPECT_TRUE( + matchesWithFixedpoint("_Accum i = 1.25ulk;", HasFixedPointLiteral)); + EXPECT_TRUE(matchesWithFixedpoint("_Accum decexp1 = 1.575e1k;", + HasFixedPointLiteral)); + EXPECT_TRUE( + matchesWithFixedpoint("_Accum hex = 0x1.25fp2k;", HasFixedPointLiteral)); + EXPECT_TRUE(matchesWithFixedpoint("_Sat long _Fract i = 0.25r;", + HasFixedPointLiteral)); + EXPECT_TRUE(matchesWithFixedpoint("_Sat short _Accum i = 256.0k;", + HasFixedPointLiteral)); + EXPECT_TRUE(matchesWithFixedpoint( + "_Accum i = 256.0k;", + fixedPointLiteral(equals(llvm::APInt(32, 0x800000, true))))); + EXPECT_TRUE(matchesWithFixedpoint( + "_Fract i = 0.25ulr;", + fixedPointLiteral(equals(llvm::APInt(32, 0x40000000, false))))); + EXPECT_TRUE(matchesWithFixedpoint( + "_Fract i = 0.5hr;", + fixedPointLiteral(equals(llvm::APInt(8, 0x40, true))))); + + EXPECT_TRUE( + notMatchesWithFixedpoint("short _Accum i = 2u;", HasFixedPointLiteral)); + EXPECT_TRUE( + notMatchesWithFixedpoint("short _Accum i = 2;", HasFixedPointLiteral)); + EXPECT_TRUE( + notMatchesWithFixedpoint("_Accum i = 1.25;", HasFixedPointLiteral)); + EXPECT_TRUE(notMatchesWithFixedpoint("_Accum i = (double)(1.25 * 4.5i);", + HasFixedPointLiteral)); + EXPECT_TRUE(notMatchesWithFixedpoint( + "_Accum i = 256.0k;", + fixedPointLiteral(equals(llvm::APInt(32, 0x800001, true))))); + EXPECT_TRUE(notMatchesWithFixedpoint( + "_Fract i = 0.25ulr;", + fixedPointLiteral(equals(llvm::APInt(32, 0x40000001, false))))); + EXPECT_TRUE(notMatchesWithFixedpoint( + "_Fract i = 0.5hr;", + fixedPointLiteral(equals(llvm::APInt(8, 0x41, true))))); +} + TEST_P(ASTMatchersTest, CXXNullPtrLiteralExpr) { if (!GetParam().isCXX11OrLater()) { return; diff --git a/clang/unittests/ASTMatchers/ASTMatchersTest.h b/clang/unittests/ASTMatchers/ASTMatchersTest.h index ad2f5f355621c..4c6320a2aff60 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTest.h +++ b/clang/unittests/ASTMatchers/ASTMatchersTest.h @@ -289,6 +289,20 @@ testing::AssertionResult notMatchesWithOpenMP51(const Twine &Code, {"-fopenmp=libomp", "-fopenmp-version=51"}); } +template +testing::AssertionResult matchesWithFixedpoint(const std::string &Code, + const T &AMatcher) { + return matchesConditionally(Code, AMatcher, true, {"-ffixed-point"}, + FileContentMappings(), "input.c"); +} + +template +testing::AssertionResult notMatchesWithFixedpoint(const std::string &Code, + const T &AMatcher) { + return matchesConditionally(Code, AMatcher, false, {"-ffixed-point"}, + FileContentMappings(), "input.c"); +} + template testing::AssertionResult matchAndVerifyResultConditionally( const Twine &Code, const T &AMatcher,