diff --git a/clang-tools-extra/pseudo/lib/cxx/CXX.cpp b/clang-tools-extra/pseudo/lib/cxx/CXX.cpp --- a/clang-tools-extra/pseudo/lib/cxx/CXX.cpp +++ b/clang-tools-extra/pseudo/lib/cxx/CXX.cpp @@ -13,6 +13,7 @@ #include "clang-pseudo/grammar/LRTable.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/TokenKinds.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Debug.h" #include @@ -109,6 +110,48 @@ assert(RHS.size() == 1 && RHS.front()->symbol() == Kind); return *RHS.front(); } +enum IDKind : unsigned { + // Type + Class = 1 << 0, + Enum = 1 << 1, + Typedef = 1 << 2, + + Namespace = 1 << 3, + NamespaceAlias = 1 << 4, + + Function = 1 << 5, + + Template = 1 << 6, + TemplateFunction = Template | Function, + TemplateClass = Template | Class, + TemplateTypedef = Template | Typedef, +}; +inline IDKind operator|(IDKind L, IDKind R) { + return static_cast(static_cast(L) | + static_cast(R)); +} +inline IDKind operator&(IDKind A, IDKind B) { + return static_cast(static_cast(A) & static_cast(B)); +} + +llvm::StringMap *IDTable = []() { + auto *Results = new llvm::StringMap({ + {"dyn_cast", IDKind::Function | IDKind::Template}, + + }); + for (auto Namespace : {"llvm", "trace", "clangd", "clang", "std"}) + Results->insert({Namespace, IDKind::Namespace}); + for (auto Class : + {"SourceManager", "ReferenceLoc", "NamedDecl", "NamespaceDecl", + "NamedDecl", "ASTSignals", "ParsedAST", "ASTSignals", "Span", + "SymbolID", "string", "NamespaceDecl"}) + Results->insert({Class, IDKind::Class}); + for (auto Expression : {"isInsideMainFile", "findExplicitReferences", + "getSymbolID", "printNamespaceScope"}) + Results->insert({Expression, IDKind::Function}); + + return Results; +}(); bool isFunctionDeclarator(const ForestNode *Declarator) { assert(Declarator->symbol() == (SymbolID)(cxx::Symbol::declarator)); @@ -266,6 +309,27 @@ } llvm::DenseMap buildGuards() { +#define HAS_BIT(value) \ + [](const GuardParams &P) -> bool { \ + const auto &T = P.Tokens.tokens()[P.RHS.front()->startTokenIndex()]; \ + if (T.Kind != tok::identifier) \ + return true; \ + auto It = IDTable->find(T.text()); \ + if (It == IDTable->end()) \ + return true; \ + return (value)&It->second; \ + } +#define EXACT_BIT(value) \ + [](const GuardParams &P) -> bool { \ + const auto &T = P.Tokens.tokens()[P.RHS.front()->startTokenIndex()]; \ + if (T.Kind != tok::identifier) \ + return true; \ + auto It = IDTable->find(T.text()); \ + if (It == IDTable->end()) \ + return true; \ + return (value) == It->second; \ + } + #define GUARD(cond) \ { \ [](const GuardParams &P) { return cond; } \ @@ -280,7 +344,20 @@ const ForestNode &N = onlySymbol((SymbolID)Symbol::kind, P.RHS, P.Tokens); \ return cond; \ } + return { + {(RuleID)Rule::class_name_0identifier, HAS_BIT(Class)}, + {(RuleID)Rule::template_name_0identifier, HAS_BIT(Template)}, + {(RuleID)Rule::enum_name_0identifier, HAS_BIT(Enum)}, + {(RuleID)Rule::typedef_name_0identifier, HAS_BIT(Typedef)}, + {(RuleID)Rule::namespace_name_0identifier, HAS_BIT(Namespace)}, + {(RuleID)Rule::namespace_alias_0identifier, HAS_BIT(NamespaceAlias)}, + // expression that refers to a function. + {(RuleID)Rule::id_expression_0unqualified_id, HAS_BIT(Function)}, + + {(RuleID)Rule::class_name_0simple_template_id, EXACT_BIT((IDKind::TemplateClass))}, + {(RuleID)Rule::typedef_name_0simple_template_id, EXACT_BIT(IDKind::TemplateTypedef)}, + {(RuleID)Rule::function_declarator_0declarator, SYMBOL_GUARD(declarator, isFunctionDeclarator(&N))}, {(RuleID)Rule::non_function_declarator_0declarator, diff --git a/clang-tools-extra/pseudo/lib/cxx/cxx.bnf b/clang-tools-extra/pseudo/lib/cxx/cxx.bnf --- a/clang-tools-extra/pseudo/lib/cxx/cxx.bnf +++ b/clang-tools-extra/pseudo/lib/cxx/cxx.bnf @@ -34,15 +34,15 @@ _ := declaration-seq # gram.key -typedef-name := IDENTIFIER -typedef-name := simple-template-id -namespace-name := IDENTIFIER -namespace-name := namespace-alias -namespace-alias := IDENTIFIER -class-name := IDENTIFIER -class-name := simple-template-id -enum-name := IDENTIFIER -template-name := IDENTIFIER +typedef-name := IDENTIFIER [guard] +typedef-name := simple-template-id [guard] +namespace-name := IDENTIFIER [guard] +namespace-name := namespace-alias [guard] +namespace-alias := IDENTIFIER [guard] +class-name := IDENTIFIER [guard] +class-name := simple-template-id [guard] +enum-name := IDENTIFIER [guard] +template-name := IDENTIFIER [guard] # gram.basic #! Custom modifications to eliminate optional declaration-seq @@ -58,7 +58,7 @@ primary-expression := lambda-expression primary-expression := fold-expression primary-expression := requires-expression -id-expression := unqualified-id +id-expression := unqualified-id [guard] id-expression := qualified-id unqualified-id := IDENTIFIER unqualified-id := operator-function-id