diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-10 13:44:22 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-10 13:44:22 +0000 |
commit | 1b08b196ac845675036ac78f3ac927d0a37f707c (patch) | |
tree | 1fbd923674e903831dc097fdb4fdfd64dd6e47b1 /lib/ASTMatchers/Dynamic | |
parent | 551c698530debaae81139c7c76a29fb762793362 (diff) |
Diffstat (limited to 'lib/ASTMatchers/Dynamic')
-rw-r--r-- | lib/ASTMatchers/Dynamic/Diagnostics.cpp | 4 | ||||
-rw-r--r-- | lib/ASTMatchers/Dynamic/Marshallers.h | 20 | ||||
-rw-r--r-- | lib/ASTMatchers/Dynamic/Parser.cpp | 63 | ||||
-rw-r--r-- | lib/ASTMatchers/Dynamic/Registry.cpp | 28 | ||||
-rw-r--r-- | lib/ASTMatchers/Dynamic/VariantValue.cpp | 64 |
5 files changed, 153 insertions, 26 deletions
diff --git a/lib/ASTMatchers/Dynamic/Diagnostics.cpp b/lib/ASTMatchers/Dynamic/Diagnostics.cpp index 787b780c4243..9cddcf93caef 100644 --- a/lib/ASTMatchers/Dynamic/Diagnostics.cpp +++ b/lib/ASTMatchers/Dynamic/Diagnostics.cpp @@ -118,8 +118,8 @@ static StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) { return "Malformed bind() expression."; case Diagnostics::ET_ParserTrailingCode: return "Expected end of code."; - case Diagnostics::ET_ParserUnsignedError: - return "Error parsing unsigned token: <$0>"; + case Diagnostics::ET_ParserNumberError: + return "Error parsing numeric literal: <$0>"; case Diagnostics::ET_ParserOverloadedType: return "Input value has unresolved overloaded type: $0"; diff --git a/lib/ASTMatchers/Dynamic/Marshallers.h b/lib/ASTMatchers/Dynamic/Marshallers.h index fb6b349a811c..c557ff162691 100644 --- a/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/lib/ASTMatchers/Dynamic/Marshallers.h @@ -65,6 +65,26 @@ template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > { } }; +template <> struct ArgTypeTraits<bool> { + static bool is(const VariantValue &Value) { return Value.isBoolean(); } + static bool get(const VariantValue &Value) { + return Value.getBoolean(); + } + static ArgKind getKind() { + return ArgKind(ArgKind::AK_Boolean); + } +}; + +template <> struct ArgTypeTraits<double> { + static bool is(const VariantValue &Value) { return Value.isDouble(); } + static double get(const VariantValue &Value) { + return Value.getDouble(); + } + static ArgKind getKind() { + return ArgKind(ArgKind::AK_Double); + } +}; + template <> struct ArgTypeTraits<unsigned> { static bool is(const VariantValue &Value) { return Value.isUnsigned(); } static unsigned get(const VariantValue &Value) { diff --git a/lib/ASTMatchers/Dynamic/Parser.cpp b/lib/ASTMatchers/Dynamic/Parser.cpp index ce8d0a9a0206..f5bd29668995 100644 --- a/lib/ASTMatchers/Dynamic/Parser.cpp +++ b/lib/ASTMatchers/Dynamic/Parser.cpp @@ -130,8 +130,8 @@ private: case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - // Parse an unsigned literal. - consumeUnsignedLiteral(&Result); + // Parse an unsigned and float literal. + consumeNumberLiteral(&Result); break; default: @@ -153,8 +153,16 @@ private: break; ++TokenLength; } - Result.Kind = TokenInfo::TK_Ident; - Result.Text = Code.substr(0, TokenLength); + if (TokenLength == 4 && Code.startswith("true")) { + Result.Kind = TokenInfo::TK_Literal; + Result.Value = true; + } else if (TokenLength == 5 && Code.startswith("false")) { + Result.Kind = TokenInfo::TK_Literal; + Result.Value = false; + } else { + Result.Kind = TokenInfo::TK_Ident; + Result.Text = Code.substr(0, TokenLength); + } Code = Code.drop_front(TokenLength); } else { Result.Kind = TokenInfo::TK_InvalidChar; @@ -168,8 +176,9 @@ private: return Result; } - /// \brief Consume an unsigned literal. - void consumeUnsignedLiteral(TokenInfo *Result) { + /// \brief Consume an unsigned and float literal. + void consumeNumberLiteral(TokenInfo *Result) { + bool isFloatingLiteral = false; unsigned Length = 1; if (Code.size() > 1) { // Consume the 'x' or 'b' radix modifier, if present. @@ -180,20 +189,44 @@ private: while (Length < Code.size() && isHexDigit(Code[Length])) ++Length; + // Try to recognize a floating point literal. + while (Length < Code.size()) { + char c = Code[Length]; + if (c == '-' || c == '+' || c == '.' || isHexDigit(c)) { + isFloatingLiteral = true; + Length++; + } else { + break; + } + } + Result->Text = Code.substr(0, Length); Code = Code.drop_front(Length); - unsigned Value; - if (!Result->Text.getAsInteger(0, Value)) { - Result->Kind = TokenInfo::TK_Literal; - Result->Value = Value; + if (isFloatingLiteral) { + char *end; + errno = 0; + std::string Text = Result->Text.str(); + double doubleValue = strtod(Text.c_str(), &end); + if (*end == 0 && errno == 0) { + Result->Kind = TokenInfo::TK_Literal; + Result->Value = doubleValue; + return; + } } else { - SourceRange Range; - Range.Start = Result->Range.Start; - Range.End = currentLocation(); - Error->addError(Range, Error->ET_ParserUnsignedError) << Result->Text; - Result->Kind = TokenInfo::TK_Error; + unsigned Value; + if (!Result->Text.getAsInteger(0, Value)) { + Result->Kind = TokenInfo::TK_Literal; + Result->Value = Value; + return; + } } + + SourceRange Range; + Range.Start = Result->Range.Start; + Range.End = currentLocation(); + Error->addError(Range, Error->ET_ParserNumberError) << Result->Text; + Result->Kind = TokenInfo::TK_Error; } /// \brief Consume a string literal. diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp index 26743d86f5e7..031ceb320306 100644 --- a/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/lib/ASTMatchers/Dynamic/Registry.cpp @@ -56,20 +56,24 @@ void RegistryMaps::registerMatcher( registerMatcher(#name, internal::makeMatcherAutoMarshall( \ ::clang::ast_matchers::name, #name)); +#define REGISTER_MATCHER_OVERLOAD(name) \ + registerMatcher(#name, \ + llvm::make_unique<internal::OverloadedMatcherDescriptor>(name##Callbacks)) + #define SPECIFIC_MATCHER_OVERLOAD(name, Id) \ static_cast<::clang::ast_matchers::name##_Type##Id>( \ ::clang::ast_matchers::name) +#define MATCHER_OVERLOAD_ENTRY(name, Id) \ + internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, Id), \ + #name) + #define REGISTER_OVERLOADED_2(name) \ do { \ - std::unique_ptr<MatcherDescriptor> Callbacks[] = { \ - internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 0), \ - #name), \ - internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 1), \ - #name)}; \ - registerMatcher( \ - #name, \ - llvm::make_unique<internal::OverloadedMatcherDescriptor>(Callbacks)); \ + std::unique_ptr<MatcherDescriptor> name##Callbacks[] = { \ + MATCHER_OVERLOAD_ENTRY(name, 0), \ + MATCHER_OVERLOAD_ENTRY(name, 1)}; \ + REGISTER_MATCHER_OVERLOAD(name); \ } while (0) /// \brief Generate a registry map with all the known matchers. @@ -83,7 +87,6 @@ RegistryMaps::RegistryMaps() { // findAll // // Other: - // equals // equalsNode REGISTER_OVERLOADED_2(callee); @@ -96,6 +99,13 @@ RegistryMaps::RegistryMaps() { REGISTER_OVERLOADED_2(references); REGISTER_OVERLOADED_2(thisPointerType); + std::unique_ptr<MatcherDescriptor> equalsCallbacks[] = { + MATCHER_OVERLOAD_ENTRY(equals, 0), + MATCHER_OVERLOAD_ENTRY(equals, 1), + MATCHER_OVERLOAD_ENTRY(equals, 2), + }; + REGISTER_MATCHER_OVERLOAD(equals); + REGISTER_MATCHER(accessSpecDecl); REGISTER_MATCHER(addrLabelExpr); REGISTER_MATCHER(alignOfExpr); diff --git a/lib/ASTMatchers/Dynamic/VariantValue.cpp b/lib/ASTMatchers/Dynamic/VariantValue.cpp index f0339ed479cd..57858d00acb4 100644 --- a/lib/ASTMatchers/Dynamic/VariantValue.cpp +++ b/lib/ASTMatchers/Dynamic/VariantValue.cpp @@ -24,6 +24,10 @@ std::string ArgKind::asString() const { switch (getArgKind()) { case AK_Matcher: return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str(); + case AK_Boolean: + return "boolean"; + case AK_Double: + return "double"; case AK_Unsigned: return "unsigned"; case AK_String: @@ -247,6 +251,14 @@ VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) { *this = Other; } +VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) { + setBoolean(Boolean); +} + +VariantValue::VariantValue(double Double) : Type(VT_Nothing) { + setDouble(Double); +} + VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) { setUnsigned(Unsigned); } @@ -265,6 +277,12 @@ VariantValue &VariantValue::operator=(const VariantValue &Other) { if (this == &Other) return *this; reset(); switch (Other.Type) { + case VT_Boolean: + setBoolean(Other.getBoolean()); + break; + case VT_Double: + setDouble(Other.getDouble()); + break; case VT_Unsigned: setUnsigned(Other.getUnsigned()); break; @@ -290,6 +308,8 @@ void VariantValue::reset() { delete Value.Matcher; break; // Cases that do nothing. + case VT_Boolean: + case VT_Double: case VT_Unsigned: case VT_Nothing: break; @@ -297,6 +317,36 @@ void VariantValue::reset() { Type = VT_Nothing; } +bool VariantValue::isBoolean() const { + return Type == VT_Boolean; +} + +bool VariantValue::getBoolean() const { + assert(isBoolean()); + return Value.Boolean; +} + +void VariantValue::setBoolean(bool NewValue) { + reset(); + Type = VT_Boolean; + Value.Boolean = NewValue; +} + +bool VariantValue::isDouble() const { + return Type == VT_Double; +} + +double VariantValue::getDouble() const { + assert(isDouble()); + return Value.Double; +} + +void VariantValue::setDouble(double NewValue) { + reset(); + Type = VT_Double; + Value.Double = NewValue; +} + bool VariantValue::isUnsigned() const { return Type == VT_Unsigned; } @@ -344,6 +394,18 @@ void VariantValue::setMatcher(const VariantMatcher &NewValue) { bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const { switch (Kind.getArgKind()) { + case ArgKind::AK_Boolean: + if (!isBoolean()) + return false; + *Specificity = 1; + return true; + + case ArgKind::AK_Double: + if (!isDouble()) + return false; + *Specificity = 1; + return true; + case ArgKind::AK_Unsigned: if (!isUnsigned()) return false; @@ -383,6 +445,8 @@ std::string VariantValue::getTypeAsString() const { switch (Type) { case VT_String: return "String"; case VT_Matcher: return getMatcher().getTypeAsString(); + case VT_Boolean: return "Boolean"; + case VT_Double: return "Double"; case VT_Unsigned: return "Unsigned"; case VT_Nothing: return "Nothing"; } |