aboutsummaryrefslogtreecommitdiff
path: root/lib/ASTMatchers/Dynamic/Registry.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ASTMatchers/Dynamic/Registry.cpp')
-rw-r--r--lib/ASTMatchers/Dynamic/Registry.cpp211
1 files changed, 190 insertions, 21 deletions
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index 70e956e65465..4bc50a0f2a96 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -13,23 +13,24 @@
//===------------------------------------------------------------===//
#include "clang/ASTMatchers/Dynamic/Registry.h"
-
-#include <utility>
-
#include "Marshallers.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ManagedStatic.h"
+#include <set>
+#include <utility>
+
+using namespace clang::ast_type_traits;
namespace clang {
namespace ast_matchers {
namespace dynamic {
namespace {
-using internal::MatcherCreateCallback;
+using internal::MatcherDescriptor;
-typedef llvm::StringMap<const MatcherCreateCallback *> ConstructorMap;
+typedef llvm::StringMap<const MatcherDescriptor *> ConstructorMap;
class RegistryMaps {
public:
RegistryMaps();
@@ -38,12 +39,12 @@ public:
const ConstructorMap &constructors() const { return Constructors; }
private:
- void registerMatcher(StringRef MatcherName, MatcherCreateCallback *Callback);
+ void registerMatcher(StringRef MatcherName, MatcherDescriptor *Callback);
ConstructorMap Constructors;
};
void RegistryMaps::registerMatcher(StringRef MatcherName,
- MatcherCreateCallback *Callback) {
+ MatcherDescriptor *Callback) {
assert(Constructors.find(MatcherName) == Constructors.end());
Constructors[MatcherName] = Callback;
}
@@ -58,14 +59,14 @@ void RegistryMaps::registerMatcher(StringRef MatcherName,
#define REGISTER_OVERLOADED_2(name) \
do { \
- MatcherCreateCallback *Callbacks[] = { \
+ MatcherDescriptor *Callbacks[] = { \
internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 0), \
#name), \
internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 1), \
#name) \
}; \
registerMatcher(#name, \
- new internal::OverloadedMatcherCreateCallback(Callbacks)); \
+ new internal::OverloadedMatcherDescriptor(Callbacks)); \
} while (0)
/// \brief Generate a registry map with all the known matchers.
@@ -76,11 +77,9 @@ RegistryMaps::RegistryMaps() {
// ofKind
//
// Polymorphic + argument overload:
- // unless
// findAll
//
// Other:
- // loc
// equals
// equalsNode
@@ -89,6 +88,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_OVERLOADED_2(hasType);
REGISTER_OVERLOADED_2(isDerivedFrom);
REGISTER_OVERLOADED_2(isSameOrDerivedFrom);
+ REGISTER_OVERLOADED_2(loc);
REGISTER_OVERLOADED_2(pointsTo);
REGISTER_OVERLOADED_2(references);
REGISTER_OVERLOADED_2(thisPointerType);
@@ -113,6 +113,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(builtinType);
REGISTER_MATCHER(cStyleCastExpr);
REGISTER_MATCHER(callExpr);
+ REGISTER_MATCHER(caseStmt);
REGISTER_MATCHER(castExpr);
REGISTER_MATCHER(catchStmt);
REGISTER_MATCHER(characterLiteral);
@@ -133,7 +134,9 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(declCountIs);
REGISTER_MATCHER(declRefExpr);
REGISTER_MATCHER(declStmt);
+ REGISTER_MATCHER(declaratorDecl);
REGISTER_MATCHER(defaultArgExpr);
+ REGISTER_MATCHER(defaultStmt);
REGISTER_MATCHER(deleteExpr);
REGISTER_MATCHER(dependentSizedArrayType);
REGISTER_MATCHER(destructorDecl);
@@ -143,15 +146,20 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(elaboratedType);
REGISTER_MATCHER(enumConstantDecl);
REGISTER_MATCHER(enumDecl);
+ REGISTER_MATCHER(equalsBoundNode);
REGISTER_MATCHER(explicitCastExpr);
REGISTER_MATCHER(expr);
+ REGISTER_MATCHER(exprWithCleanups);
REGISTER_MATCHER(fieldDecl);
REGISTER_MATCHER(floatLiteral);
REGISTER_MATCHER(forEach);
+ REGISTER_MATCHER(forEachConstructorInitializer);
REGISTER_MATCHER(forEachDescendant);
+ REGISTER_MATCHER(forEachSwitchCase);
REGISTER_MATCHER(forField);
REGISTER_MATCHER(forRangeStmt);
REGISTER_MATCHER(forStmt);
+ REGISTER_MATCHER(friendDecl);
REGISTER_MATCHER(functionDecl);
REGISTER_MATCHER(functionTemplateDecl);
REGISTER_MATCHER(functionType);
@@ -170,6 +178,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasBase);
REGISTER_MATCHER(hasBody);
REGISTER_MATCHER(hasCanonicalType);
+ REGISTER_MATCHER(hasCaseConstant);
REGISTER_MATCHER(hasCondition);
REGISTER_MATCHER(hasConditionVariableStatement);
REGISTER_MATCHER(hasDeclContext);
@@ -180,12 +189,14 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasEitherOperand);
REGISTER_MATCHER(hasElementType);
REGISTER_MATCHER(hasFalseExpression);
+ REGISTER_MATCHER(hasGlobalStorage);
REGISTER_MATCHER(hasImplicitDestinationType);
REGISTER_MATCHER(hasIncrement);
REGISTER_MATCHER(hasIndex);
REGISTER_MATCHER(hasInitializer);
REGISTER_MATCHER(hasLHS);
REGISTER_MATCHER(hasLocalQualifiers);
+ REGISTER_MATCHER(hasLocalStorage);
REGISTER_MATCHER(hasLoopInit);
REGISTER_MATCHER(hasMethod);
REGISTER_MATCHER(hasName);
@@ -203,6 +214,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasTargetDecl);
REGISTER_MATCHER(hasTemplateArgument);
REGISTER_MATCHER(hasTrueExpression);
+ REGISTER_MATCHER(hasTypeLoc);
REGISTER_MATCHER(hasUnaryOperand);
REGISTER_MATCHER(hasValueType);
REGISTER_MATCHER(ifStmt);
@@ -215,12 +227,15 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(innerType);
REGISTER_MATCHER(integerLiteral);
REGISTER_MATCHER(isArrow);
+ REGISTER_MATCHER(isConst);
REGISTER_MATCHER(isConstQualified);
REGISTER_MATCHER(isDefinition);
REGISTER_MATCHER(isExplicitTemplateSpecialization);
+ REGISTER_MATCHER(isExpr);
REGISTER_MATCHER(isExternC);
REGISTER_MATCHER(isImplicit);
REGISTER_MATCHER(isInteger);
+ REGISTER_MATCHER(isListInitialization);
REGISTER_MATCHER(isOverride);
REGISTER_MATCHER(isPrivate);
REGISTER_MATCHER(isProtected);
@@ -252,6 +267,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(operatorCallExpr);
REGISTER_MATCHER(parameterCountIs);
REGISTER_MATCHER(parenType);
+ REGISTER_MATCHER(parmVarDecl);
REGISTER_MATCHER(pointee);
REGISTER_MATCHER(pointerType);
REGISTER_MATCHER(qualType);
@@ -275,6 +291,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(switchCase);
REGISTER_MATCHER(switchStmt);
REGISTER_MATCHER(templateSpecializationType);
+ REGISTER_MATCHER(temporaryObjectExpr);
REGISTER_MATCHER(thisExpr);
REGISTER_MATCHER(throughUsingDecl);
REGISTER_MATCHER(throwExpr);
@@ -285,6 +302,10 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(typedefType);
REGISTER_MATCHER(unaryExprOrTypeTraitExpr);
REGISTER_MATCHER(unaryOperator);
+ REGISTER_MATCHER(unaryTransformType);
+ REGISTER_MATCHER(unless);
+ REGISTER_MATCHER(unresolvedConstructExpr);
+ REGISTER_MATCHER(unresolvedUsingValueDecl);
REGISTER_MATCHER(userDefinedLiteral);
REGISTER_MATCHER(usingDecl);
REGISTER_MATCHER(varDecl);
@@ -306,27 +327,175 @@ static llvm::ManagedStatic<RegistryMaps> RegistryData;
} // anonymous namespace
// static
-VariantMatcher Registry::constructMatcher(StringRef MatcherName,
- const SourceRange &NameRange,
- ArrayRef<ParserValue> Args,
- Diagnostics *Error) {
+llvm::Optional<MatcherCtor> Registry::lookupMatcherCtor(StringRef MatcherName) {
ConstructorMap::const_iterator it =
RegistryData->constructors().find(MatcherName);
- if (it == RegistryData->constructors().end()) {
- Error->addError(NameRange, Error->ET_RegistryNotFound) << MatcherName;
- return VariantMatcher();
+ return it == RegistryData->constructors().end()
+ ? llvm::Optional<MatcherCtor>()
+ : it->second;
+}
+
+namespace {
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const std::set<ASTNodeKind> &KS) {
+ unsigned Count = 0;
+ for (std::set<ASTNodeKind>::const_iterator I = KS.begin(), E = KS.end();
+ I != E; ++I) {
+ if (I != KS.begin())
+ OS << "|";
+ if (Count++ == 3) {
+ OS << "...";
+ break;
+ }
+ OS << *I;
+ }
+ return OS;
+}
+
+struct ReverseSpecificityThenName {
+ bool operator()(const std::pair<unsigned, std::string> &A,
+ const std::pair<unsigned, std::string> &B) const {
+ return A.first > B.first || (A.first == B.first && A.second < B.second);
}
+};
+
+}
+
+std::vector<MatcherCompletion> Registry::getCompletions(
+ ArrayRef<std::pair<MatcherCtor, unsigned> > Context) {
+ ASTNodeKind InitialTypes[] = {
+ ASTNodeKind::getFromNodeKind<Decl>(),
+ ASTNodeKind::getFromNodeKind<QualType>(),
+ ASTNodeKind::getFromNodeKind<Type>(),
+ ASTNodeKind::getFromNodeKind<Stmt>(),
+ ASTNodeKind::getFromNodeKind<NestedNameSpecifier>(),
+ ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>(),
+ ASTNodeKind::getFromNodeKind<TypeLoc>()
+ };
+ ArrayRef<ASTNodeKind> InitialTypesRef(InitialTypes);
- return it->second->run(NameRange, Args, Error);
+ // Starting with the above seed of acceptable top-level matcher types, compute
+ // the acceptable type set for the argument indicated by each context element.
+ std::set<ASTNodeKind> TypeSet(InitialTypesRef.begin(), InitialTypesRef.end());
+ for (ArrayRef<std::pair<MatcherCtor, unsigned> >::iterator
+ CtxI = Context.begin(),
+ CtxE = Context.end();
+ CtxI != CtxE; ++CtxI) {
+ std::vector<internal::ArgKind> NextTypeSet;
+ for (std::set<ASTNodeKind>::iterator I = TypeSet.begin(), E = TypeSet.end();
+ I != E; ++I) {
+ if (CtxI->first->isConvertibleTo(*I) &&
+ (CtxI->first->isVariadic() ||
+ CtxI->second < CtxI->first->getNumArgs()))
+ CtxI->first->getArgKinds(*I, CtxI->second, NextTypeSet);
+ }
+ TypeSet.clear();
+ for (std::vector<internal::ArgKind>::iterator I = NextTypeSet.begin(),
+ E = NextTypeSet.end();
+ I != E; ++I) {
+ if (I->getArgKind() == internal::ArgKind::AK_Matcher)
+ TypeSet.insert(I->getMatcherKind());
+ }
+ }
+
+ typedef std::map<std::pair<unsigned, std::string>, MatcherCompletion,
+ ReverseSpecificityThenName> CompletionsTy;
+ CompletionsTy Completions;
+
+ // TypeSet now contains the list of acceptable types for the argument we are
+ // completing. Search the registry for acceptable matchers.
+ for (ConstructorMap::const_iterator I = RegistryData->constructors().begin(),
+ E = RegistryData->constructors().end();
+ I != E; ++I) {
+ std::set<ASTNodeKind> RetKinds;
+ unsigned NumArgs = I->second->isVariadic() ? 1 : I->second->getNumArgs();
+ bool IsPolymorphic = I->second->isPolymorphic();
+ std::vector<std::vector<internal::ArgKind> > ArgsKinds(NumArgs);
+ unsigned MaxSpecificity = 0;
+ for (std::set<ASTNodeKind>::iterator TI = TypeSet.begin(),
+ TE = TypeSet.end();
+ TI != TE; ++TI) {
+ unsigned Specificity;
+ ASTNodeKind LeastDerivedKind;
+ if (I->second->isConvertibleTo(*TI, &Specificity, &LeastDerivedKind)) {
+ if (MaxSpecificity < Specificity)
+ MaxSpecificity = Specificity;
+ RetKinds.insert(LeastDerivedKind);
+ for (unsigned Arg = 0; Arg != NumArgs; ++Arg)
+ I->second->getArgKinds(*TI, Arg, ArgsKinds[Arg]);
+ if (IsPolymorphic)
+ break;
+ }
+ }
+
+ if (!RetKinds.empty() && MaxSpecificity > 0) {
+ std::string Decl;
+ llvm::raw_string_ostream OS(Decl);
+
+ if (IsPolymorphic) {
+ OS << "Matcher<T> " << I->first() << "(Matcher<T>";
+ } else {
+ OS << "Matcher<" << RetKinds << "> " << I->first() << "(";
+ for (std::vector<std::vector<internal::ArgKind> >::iterator
+ KI = ArgsKinds.begin(),
+ KE = ArgsKinds.end();
+ KI != KE; ++KI) {
+ if (KI != ArgsKinds.begin())
+ OS << ", ";
+ // This currently assumes that a matcher may not overload a
+ // non-matcher, and all non-matcher overloads have identical
+ // arguments.
+ if ((*KI)[0].getArgKind() == internal::ArgKind::AK_Matcher) {
+ std::set<ASTNodeKind> MatcherKinds;
+ std::transform(
+ KI->begin(), KI->end(),
+ std::inserter(MatcherKinds, MatcherKinds.end()),
+ std::mem_fun_ref(&internal::ArgKind::getMatcherKind));
+ OS << "Matcher<" << MatcherKinds << ">";
+ } else {
+ OS << (*KI)[0].asString();
+ }
+ }
+ }
+ if (I->second->isVariadic())
+ OS << "...";
+ OS << ")";
+
+ std::string TypedText = I->first();
+ TypedText += "(";
+ if (ArgsKinds.empty())
+ TypedText += ")";
+ else if (ArgsKinds[0][0].getArgKind() == internal::ArgKind::AK_String)
+ TypedText += "\"";
+
+ Completions[std::make_pair(MaxSpecificity, I->first())] =
+ MatcherCompletion(TypedText, OS.str());
+ }
+ }
+
+ std::vector<MatcherCompletion> RetVal;
+ for (CompletionsTy::iterator I = Completions.begin(), E = Completions.end();
+ I != E; ++I)
+ RetVal.push_back(I->second);
+ return RetVal;
+}
+
+// static
+VariantMatcher Registry::constructMatcher(MatcherCtor Ctor,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) {
+ return Ctor->create(NameRange, Args, Error);
}
// static
-VariantMatcher Registry::constructBoundMatcher(StringRef MatcherName,
+VariantMatcher Registry::constructBoundMatcher(MatcherCtor Ctor,
const SourceRange &NameRange,
StringRef BindID,
ArrayRef<ParserValue> Args,
Diagnostics *Error) {
- VariantMatcher Out = constructMatcher(MatcherName, NameRange, Args, Error);
+ VariantMatcher Out = constructMatcher(Ctor, NameRange, Args, Error);
if (Out.isNull()) return Out;
llvm::Optional<DynTypedMatcher> Result = Out.getSingleMatcher();