Index: clang-tools-extra/trunk/include-fixer/InMemoryXrefsDB.cpp =================================================================== --- clang-tools-extra/trunk/include-fixer/InMemoryXrefsDB.cpp +++ clang-tools-extra/trunk/include-fixer/InMemoryXrefsDB.cpp @@ -28,7 +28,8 @@ *IdentiferContext); } - SymbolInfo Symbol(Names.back(), SymbolInfo::Class, Header, Contexts, 1); + SymbolInfo Symbol(Names.back(), SymbolInfo::SymbolKind::Class, Header, + Contexts, 1); this->LookupTable[Symbol.getName()].push_back(Symbol); } } Index: clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp =================================================================== --- clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp +++ clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp @@ -23,6 +23,13 @@ namespace clang { namespace find_all_symbols { namespace { + +AST_MATCHER(EnumConstantDecl, isInScopedEnum) { + if (const auto *ED = dyn_cast(Node.getDeclContext())) + return ED->isScoped(); + return false; +} + std::vector GetContexts(const NamedDecl *ND) { std::vector Contexts; for (const auto *Context = ND->getDeclContext(); Context; @@ -34,12 +41,16 @@ assert(llvm::isa(Context) && "Expect Context to be a NamedDecl"); if (const auto *NSD = dyn_cast(Context)) { - Contexts.emplace_back(SymbolInfo::Namespace, NSD->isAnonymousNamespace() - ? "" - : NSD->getName().str()); + Contexts.emplace_back(SymbolInfo::ContextType::Namespace, + NSD->isAnonymousNamespace() ? "" + : NSD->getName().str()); + } else if (const auto *ED = dyn_cast(Context)) { + Contexts.emplace_back(SymbolInfo::ContextType::EnumDecl, + ED->getName().str()); } else { const auto *RD = cast(Context); - Contexts.emplace_back(SymbolInfo::Record, RD->getName().str()); + Contexts.emplace_back(SymbolInfo::ContextType::Record, + RD->getName().str()); } } return Contexts; @@ -49,19 +60,24 @@ const SourceManager &SM) { SymbolInfo::SymbolKind Type; if (llvm::isa(ND)) { - Type = SymbolInfo::Variable; + Type = SymbolInfo::SymbolKind::Variable; } else if (llvm::isa(ND)) { - Type = SymbolInfo::Function; + Type = SymbolInfo::SymbolKind::Function; } else if (llvm::isa(ND)) { - Type = SymbolInfo::TypedefName; + Type = SymbolInfo::SymbolKind::TypedefName; + } else if (llvm::isa(ND)) { + Type = SymbolInfo::SymbolKind::EnumConstantDecl; + } else if (llvm::isa(ND)) { + Type = SymbolInfo::SymbolKind::EnumDecl; } else { - assert(llvm::isa(ND) && "Matched decl must be one of VarDecl, " - "FunctionDecl, TypedefNameDecl and " - "RecordDecl!"); + assert(llvm::isa(ND) && + "Matched decl must be one of VarDecl, " + "FunctionDecl, TypedefNameDecl, EnumConstantDecl, " + "EnumDecl and RecordDecl!"); // C-style record decl can have empty name, e.g "struct { ... } var;". if (ND->getName().empty()) return llvm::None; - Type = SymbolInfo::Class; + Type = SymbolInfo::SymbolKind::Class; } SourceLocation Loc = SM.getExpansionLoc(ND->getLocation()); @@ -159,6 +175,23 @@ hasDeclContext(linkageSpecDecl()))) .bind("decl"), this); + + // Matchers for enum declarations. + MatchFinder->addMatcher( + enumDecl(CommonFilter, anyOf(HasNSOrTUCtxMatcher, ExternCMatcher)) + .bind("decl"), + this); + + // Matchers for enum constant declarations. + // We only match the enum constants in non-scoped enum declarations which are + // inside toplevel translation unit or a namespace. + MatchFinder->addMatcher( + enumConstantDecl( + CommonFilter, + unless(isInScopedEnum()), + anyOf(hasDeclContext(enumDecl(HasNSOrTUCtxMatcher)), ExternCMatcher)) + .bind("decl"), + this); } void FindAllSymbols::run(const MatchFinder::MatchResult &Result) { Index: clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h =================================================================== --- clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h +++ clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h @@ -25,18 +25,21 @@ class SymbolInfo { public: /// \brief The SymbolInfo Type. - enum SymbolKind { + enum class SymbolKind { Function, Class, Variable, TypedefName, + EnumDecl, + EnumConstantDecl, Unknown, }; /// \brief The Context Type. - enum ContextType { + enum class ContextType { Namespace, // Symbols declared in a namespace. Record, // Symbols declared in a class. + EnumDecl, // Enum constants declared in a enum declaration. }; /// \brief A pair of . @@ -44,7 +47,7 @@ // The default constructor is required by YAML traits in // LLVM_YAML_IS_DOCUMENT_LIST_VECTOR. - SymbolInfo() : Type(Unknown), LineNumber(-1) {}; + SymbolInfo() : Type(SymbolKind::Unknown), LineNumber(-1) {}; SymbolInfo(llvm::StringRef Name, SymbolKind Type, llvm::StringRef FilePath, const std::vector &Contexts, int LineNumber); Index: clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.cpp =================================================================== --- clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.cpp +++ clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.cpp @@ -49,6 +49,9 @@ io.enumCase(value, "Function", SymbolKind::Function); io.enumCase(value, "Class", SymbolKind::Class); io.enumCase(value, "TypedefName", SymbolKind::TypedefName); + io.enumCase(value, "EnumDecl", SymbolKind::EnumDecl); + io.enumCase(value, "EnumConstantDecl", SymbolKind::EnumConstantDecl); + io.enumCase(value, "Unknown", SymbolKind::Unknown); } }; Index: clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp =================================================================== --- clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp +++ clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp @@ -104,17 +104,19 @@ })"; runFindAllSymbols(Code); - SymbolInfo Symbol = - CreateSymbolInfo("xargc", SymbolInfo::Variable, HeaderName, 2, {}); + SymbolInfo Symbol = CreateSymbolInfo( + "xargc", SymbolInfo::SymbolKind::Variable, HeaderName, 2, {}); EXPECT_TRUE(hasSymbol(Symbol)); - Symbol = CreateSymbolInfo("SSSS", SymbolInfo::Variable, HeaderName, 4, - {{SymbolInfo::Namespace, "na"}}); + Symbol = + CreateSymbolInfo("SSSS", SymbolInfo::SymbolKind::Variable, HeaderName, 4, + {{SymbolInfo::ContextType::Namespace, "na"}}); EXPECT_TRUE(hasSymbol(Symbol)); - Symbol = CreateSymbolInfo( - "XXXX", SymbolInfo::Variable, HeaderName, 5, - {{SymbolInfo::Namespace, "nb"}, {SymbolInfo::Namespace, "na"}}); + Symbol = + CreateSymbolInfo("XXXX", SymbolInfo::SymbolKind::Variable, HeaderName, 5, + {{SymbolInfo::ContextType::Namespace, "nb"}, + {SymbolInfo::ContextType::Namespace, "na"}}); EXPECT_TRUE(hasSymbol(Symbol)); } @@ -128,11 +130,12 @@ })"; runFindAllSymbols(Code); - SymbolInfo Symbol = - CreateSymbolInfo("C_Func", SymbolInfo::Function, HeaderName, 3, {}); + SymbolInfo Symbol = CreateSymbolInfo( + "C_Func", SymbolInfo::SymbolKind::Function, HeaderName, 3, {}); EXPECT_TRUE(hasSymbol(Symbol)); - Symbol = CreateSymbolInfo("C_struct", SymbolInfo::Class, HeaderName, 4, {}); + Symbol = CreateSymbolInfo("C_struct", SymbolInfo::SymbolKind::Class, + HeaderName, 4, {}); EXPECT_TRUE(hasSymbol(Symbol)); } @@ -152,13 +155,18 @@ )"; runFindAllSymbols(Code); - SymbolInfo Symbol = - CreateSymbolInfo("Glob", SymbolInfo::Class, HeaderName, 2, {}); + SymbolInfo Symbol = CreateSymbolInfo("Glob", SymbolInfo::SymbolKind::Class, + HeaderName, 2, {}); EXPECT_TRUE(hasSymbol(Symbol)); - Symbol = CreateSymbolInfo("A", SymbolInfo::Class, HeaderName, 6, - {{SymbolInfo::Namespace, "na"}}); + Symbol = CreateSymbolInfo("A", SymbolInfo::SymbolKind::Class, HeaderName, 6, + {{SymbolInfo::ContextType::Namespace, "na"}}); EXPECT_TRUE(hasSymbol(Symbol)); + + Symbol = CreateSymbolInfo("AAA", SymbolInfo::SymbolKind::Class, HeaderName, 7, + {{SymbolInfo::ContextType::Record, "A"}, + {SymbolInfo::ContextType::Namespace, "na"}}); + EXPECT_FALSE(hasSymbol(Symbol)); } TEST_F(FindAllSymbolsTest, CXXRecordSymbolsTemplate) { @@ -179,8 +187,8 @@ )"; runFindAllSymbols(Code); - SymbolInfo Symbol = - CreateSymbolInfo("T_TEMP", SymbolInfo::Class, HeaderName, 3, {}); + SymbolInfo Symbol = CreateSymbolInfo("T_TEMP", SymbolInfo::SymbolKind::Class, + HeaderName, 3, {}); EXPECT_TRUE(hasSymbol(Symbol)); } @@ -200,21 +208,23 @@ )"; runFindAllSymbols(Code); - SymbolInfo Symbol = CreateSymbolInfo("gg", SymbolInfo::Function, HeaderName, - 3, {{SymbolInfo::Namespace, "na"}}); + SymbolInfo Symbol = + CreateSymbolInfo("gg", SymbolInfo::SymbolKind::Function, HeaderName, 3, + {{SymbolInfo::ContextType::Namespace, "na"}}); EXPECT_TRUE(hasSymbol(Symbol)); - Symbol = CreateSymbolInfo("f", SymbolInfo::Function, HeaderName, 4, - {{SymbolInfo::Namespace, "na"}}); + Symbol = CreateSymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, + 4, {{SymbolInfo::ContextType::Namespace, "na"}}); EXPECT_TRUE(hasSymbol(Symbol)); - Symbol = CreateSymbolInfo("SSSFFF", SymbolInfo::Function, HeaderName, 5, - {{SymbolInfo::Namespace, "na"}}); + Symbol = + CreateSymbolInfo("SSSFFF", SymbolInfo::SymbolKind::Function, HeaderName, + 5, {{SymbolInfo::ContextType::Namespace, "na"}}); EXPECT_TRUE(hasSymbol(Symbol)); - Symbol = CreateSymbolInfo( - "fun", SymbolInfo::Function, HeaderName, 10, - {{SymbolInfo::Namespace, "nb"}, {SymbolInfo::Namespace, "na"}}); + Symbol = CreateSymbolInfo("fun", SymbolInfo::SymbolKind::Function, HeaderName, + 10, {{SymbolInfo::ContextType::Namespace, "nb"}, + {SymbolInfo::ContextType::Namespace, "na"}}); EXPECT_TRUE(hasSymbol(Symbol)); } @@ -227,30 +237,30 @@ )"; runFindAllSymbols(Code); - SymbolInfo Symbol = - CreateSymbolInfo("X1", SymbolInfo::Variable, HeaderName, 2, {}); + SymbolInfo Symbol = CreateSymbolInfo("X1", SymbolInfo::SymbolKind::Variable, + HeaderName, 2, {}); EXPECT_TRUE(hasSymbol(Symbol)); - Symbol = CreateSymbolInfo("X2", SymbolInfo::Variable, HeaderName, 3, - {{SymbolInfo::Namespace, ""}}); + Symbol = CreateSymbolInfo("X2", SymbolInfo::SymbolKind::Variable, HeaderName, + 3, {{SymbolInfo::ContextType::Namespace, ""}}); EXPECT_TRUE(hasSymbol(Symbol)); - Symbol = CreateSymbolInfo( - "X3", SymbolInfo::Variable, HeaderName, 4, - {{SymbolInfo::Namespace, ""}, {SymbolInfo::Namespace, ""}}); + Symbol = CreateSymbolInfo("X3", SymbolInfo::SymbolKind::Variable, HeaderName, + 4, {{SymbolInfo::ContextType::Namespace, ""}, + {SymbolInfo::ContextType::Namespace, ""}}); EXPECT_TRUE(hasSymbol(Symbol)); - Symbol = CreateSymbolInfo( - "X4", SymbolInfo::Variable, HeaderName, 5, - {{SymbolInfo::Namespace, "nb"}, {SymbolInfo::Namespace, ""}}); + Symbol = CreateSymbolInfo("X4", SymbolInfo::SymbolKind::Variable, HeaderName, + 5, {{SymbolInfo::ContextType::Namespace, "nb"}, + {SymbolInfo::ContextType::Namespace, ""}}); EXPECT_TRUE(hasSymbol(Symbol)); } TEST_F(FindAllSymbolsTest, DecayedTypeTest) { static const char Code[] = "void DecayedFunc(int x[], int y[10]) {}"; runFindAllSymbols(Code); - SymbolInfo Symbol = - CreateSymbolInfo("DecayedFunc", SymbolInfo::Function, HeaderName, 1, {}); + SymbolInfo Symbol = CreateSymbolInfo( + "DecayedFunc", SymbolInfo::SymbolKind::Function, HeaderName, 1, {}); EXPECT_TRUE(hasSymbol(Symbol)); } @@ -262,15 +272,71 @@ )"; runFindAllSymbols(Code); - SymbolInfo Symbol = - CreateSymbolInfo("size_t_", SymbolInfo::TypedefName, HeaderName, 2, {}); + SymbolInfo Symbol = CreateSymbolInfo( + "size_t_", SymbolInfo::SymbolKind::TypedefName, HeaderName, 2, {}); + EXPECT_TRUE(hasSymbol(Symbol)); + + Symbol = CreateSymbolInfo("X", SymbolInfo::SymbolKind::TypedefName, + HeaderName, 3, {}); + EXPECT_TRUE(hasSymbol(Symbol)); + + Symbol = CreateSymbolInfo("XX", SymbolInfo::SymbolKind::TypedefName, + HeaderName, 4, {}); + EXPECT_TRUE(hasSymbol(Symbol)); +} + +TEST_F(FindAllSymbolsTest, EnumTest) { + static const char Code[] = R"( + enum Glob_E { G1, G2 }; + enum class Altitude { high='h', low='l'}; + enum { A1, A2 }; + class A { + public: + enum A_ENUM { X1, X2 }; + }; + )"; + runFindAllSymbols(Code); + + SymbolInfo Symbol = CreateSymbolInfo( + "Glob_E", SymbolInfo::SymbolKind::EnumDecl, HeaderName, 2, {}); EXPECT_TRUE(hasSymbol(Symbol)); - Symbol = CreateSymbolInfo("X", SymbolInfo::TypedefName, HeaderName, 3, {}); + Symbol = CreateSymbolInfo("G1", SymbolInfo::SymbolKind::EnumConstantDecl, + HeaderName, 2, + {{SymbolInfo::ContextType::EnumDecl, "Glob_E"}}); EXPECT_TRUE(hasSymbol(Symbol)); - Symbol = CreateSymbolInfo("XX", SymbolInfo::TypedefName, HeaderName, 4, {}); + Symbol = CreateSymbolInfo("G2", SymbolInfo::SymbolKind::EnumConstantDecl, + HeaderName, 2, + {{SymbolInfo::ContextType::EnumDecl, "Glob_E"}}); EXPECT_TRUE(hasSymbol(Symbol)); + + Symbol = CreateSymbolInfo("Altitude", SymbolInfo::SymbolKind::EnumDecl, + HeaderName, 3, {}); + EXPECT_TRUE(hasSymbol(Symbol)); + Symbol = CreateSymbolInfo("high", SymbolInfo::SymbolKind::EnumConstantDecl, + HeaderName, 3, + {{SymbolInfo::ContextType::EnumDecl, "Altitude"}}); + EXPECT_FALSE(hasSymbol(Symbol)); + + Symbol = CreateSymbolInfo("A1", SymbolInfo::SymbolKind::EnumConstantDecl, + HeaderName, 4, + {{SymbolInfo::ContextType::EnumDecl, ""}}); + EXPECT_TRUE(hasSymbol(Symbol)); + Symbol = CreateSymbolInfo("A2", SymbolInfo::SymbolKind::EnumConstantDecl, + HeaderName, 4, + {{SymbolInfo::ContextType::EnumDecl, ""}}); + EXPECT_TRUE(hasSymbol(Symbol)); + + Symbol = + CreateSymbolInfo("A_ENUM", SymbolInfo::SymbolKind::EnumDecl, HeaderName, + 7, {{SymbolInfo::ContextType::Record, "A"}}); + EXPECT_FALSE(hasSymbol(Symbol)); + + Symbol = CreateSymbolInfo("X1", SymbolInfo::SymbolKind::EnumDecl, HeaderName, + 7, {{SymbolInfo::ContextType::EnumDecl, "A_ENUM"}, + {SymbolInfo::ContextType::Record, "A"}}); + EXPECT_FALSE(hasSymbol(Symbol)); } } // namespace find_all_symbols