kfunk updated this revision to Diff 49999. kfunk added a comment. This revision is now accepted and ready to land.
Remove TODO statement http://reviews.llvm.org/D15729 Files: include/clang/Frontend/CompilerInstance.h lib/Frontend/ASTUnit.cpp lib/Frontend/CompilerInstance.cpp lib/FrontendTool/ExecuteCompilerInvocation.cpp test/CXX/drs/dr3xx.cpp unittests/Frontend/CMakeLists.txt unittests/Frontend/FrontendActionTest.cpp unittests/Frontend/PrintFunctionNamesTestPlugin/CMakeLists.txt unittests/Frontend/PrintFunctionNamesTestPlugin/PrintFunctionNamesTestPlugin.cpp
Index: unittests/Frontend/PrintFunctionNamesTestPlugin/PrintFunctionNamesTestPlugin.cpp =================================================================== --- /dev/null +++ unittests/Frontend/PrintFunctionNamesTestPlugin/PrintFunctionNamesTestPlugin.cpp @@ -0,0 +1,123 @@ +//===- PrintFunctionNames.cpp ---------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Example clang plugin which simply prints the names of all the top-level decls +// in the input file. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/AST/AST.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Sema/Sema.h" +#include "llvm/Support/raw_ostream.h" +using namespace clang; + +namespace { + +class PrintFunctionsConsumer : public ASTConsumer { + CompilerInstance &Instance; + std::set<std::string> ParsedTemplates; + +public: + PrintFunctionsConsumer(CompilerInstance &Instance, + std::set<std::string> ParsedTemplates) + : Instance(Instance), ParsedTemplates(ParsedTemplates) {} + + bool HandleTopLevelDecl(DeclGroupRef DG) override { + for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) { + const Decl *D = *i; + if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) + llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n"; + } + + return true; + } + + void HandleTranslationUnit(ASTContext& context) override { + if (!Instance.getLangOpts().DelayedTemplateParsing) + return; + + // This demonstrates how to force instantiation of some templates in + // -fdelayed-template-parsing mode. (Note: Doing this unconditionally for + // all templates is similar to not using -fdelayed-template-parsig in the + // first place.) + // The advantage of doing this in HandleTranslationUnit() is that all + // codegen (when using -add-plugin) is completely finished and this can't + // affect the compiler output. + struct Visitor : public RecursiveASTVisitor<Visitor> { + const std::set<std::string> &ParsedTemplates; + Visitor(const std::set<std::string> &ParsedTemplates) + : ParsedTemplates(ParsedTemplates) {} + bool VisitFunctionDecl(FunctionDecl *FD) { + if (FD->isLateTemplateParsed() && + ParsedTemplates.count(FD->getNameAsString())) + LateParsedDecls.insert(FD); + return true; + } + + std::set<FunctionDecl*> LateParsedDecls; + } v(ParsedTemplates); + v.TraverseDecl(context.getTranslationUnitDecl()); + clang::Sema &sema = Instance.getSema(); + for (const FunctionDecl *FD : v.LateParsedDecls) { + clang::LateParsedTemplate* LPT = sema.LateParsedTemplateMap.lookup(FD); + sema.LateTemplateParser(sema.OpaqueParser, *LPT); + llvm::errs() << "late-parsed-decl: \"" << FD->getNameAsString() << "\"\n"; + } + } +}; + +class PrintFunctionNamesAction : public PluginASTAction { + std::set<std::string> ParsedTemplates; +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef) override { + return llvm::make_unique<PrintFunctionsConsumer>(CI, ParsedTemplates); + } + + bool ParseArgs(const CompilerInstance &CI, + const std::vector<std::string> &args) override { + for (unsigned i = 0, e = args.size(); i != e; ++i) { + llvm::errs() << "PrintFunctionNames arg = " << args[i] << "\n"; + + // Example error handling. + DiagnosticsEngine &D = CI.getDiagnostics(); + if (args[i] == "-an-error") { + unsigned DiagID = D.getCustomDiagID(DiagnosticsEngine::Error, + "invalid argument '%0'"); + D.Report(DiagID) << args[i]; + return false; + } else if (args[i] == "-parse-template") { + if (i + 1 >= e) { + D.Report(D.getCustomDiagID(DiagnosticsEngine::Error, + "missing -parse-template argument")); + return false; + } + ++i; + ParsedTemplates.insert(args[i]); + } + } + if (!args.empty() && args[0] == "help") + PrintHelp(llvm::errs()); + + return true; + } + void PrintHelp(llvm::raw_ostream& ros) { + ros << "Help for PrintFunctionNames plugin goes here\n"; + } + +}; + +} + +static FrontendPluginRegistry::Add<PrintFunctionNamesAction> +X("print-fns", "print function names"); Index: unittests/Frontend/PrintFunctionNamesTestPlugin/CMakeLists.txt =================================================================== --- /dev/null +++ unittests/Frontend/PrintFunctionNamesTestPlugin/CMakeLists.txt @@ -0,0 +1,10 @@ +add_llvm_loadable_module(PrintFunctionNamesTestPlugin PrintFunctionNamesTestPlugin.cpp) + +if(LLVM_ENABLE_PLUGINS AND (WIN32 OR CYGWIN)) + target_link_libraries(PrintFunctionNamesTestPlugin ${cmake_2_8_12_PRIVATE} + clangAST + clangBasic + clangFrontend + LLVMSupport + ) +endif() Index: unittests/Frontend/FrontendActionTest.cpp =================================================================== --- unittests/Frontend/FrontendActionTest.cpp +++ unittests/Frontend/FrontendActionTest.cpp @@ -8,17 +8,21 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/FrontendAction.h" +#include "clang/Frontend/FrontendPluginRegistry.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Sema.h" #include "llvm/ADT/Triple.h" +#include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/MemoryBuffer.h" #include "gtest/gtest.h" +#include <iostream> + using namespace llvm; using namespace clang; @@ -144,6 +148,40 @@ EXPECT_EQ("c", test_action.decl_names[12]); } +bool pluginIsLoaded(const std::string &pluginName) { + for (auto it = FrontendPluginRegistry::begin(), + ie = FrontendPluginRegistry::end(); + it != ie; ++it) { + if (it->getName() == pluginName) { + return true; + } + } + return false; +} + +TEST(ASTFrontendAction, PluginLoadTest) { + CompilerInvocation *invocation = new CompilerInvocation; + invocation->getLangOpts()->CPlusPlus = true; + invocation->getPreprocessorOpts().addRemappedFile( + "test.cc", + MemoryBuffer::getMemBuffer("int main() { }").release()); + invocation->getFrontendOpts().Inputs.push_back(FrontendInputFile("test.cc", + IK_CXX)); + invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly; + invocation->getFrontendOpts().Plugins.push_back("PrintFunctionNamesTestPlugin.so"); + invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; + + CompilerInstance compiler; + compiler.setInvocation(invocation); + compiler.createDiagnostics(); + compiler.loadPlugins(); + + TestASTFrontendAction test_action(/*enableIncrementalProcessing=*/true, + /*actOnEndOfTranslationUnit=*/true); + ASSERT_TRUE(compiler.ExecuteAction(test_action)); + ASSERT_TRUE(pluginIsLoaded("print-fns")); +} + struct TestPPCallbacks : public PPCallbacks { TestPPCallbacks() : SeenEnd(false) {} Index: unittests/Frontend/CMakeLists.txt =================================================================== --- unittests/Frontend/CMakeLists.txt +++ unittests/Frontend/CMakeLists.txt @@ -1,3 +1,5 @@ +add_subdirectory(PrintFunctionNamesTestPlugin) + set(LLVM_LINK_COMPONENTS Support ) @@ -14,3 +16,4 @@ clangSema clangCodeGen ) +add_dependencies(FrontendTests PrintFunctionNamesTestPlugin) Index: test/CXX/drs/dr3xx.cpp =================================================================== --- test/CXX/drs/dr3xx.cpp +++ /dev/null @@ -1,1291 +0,0 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors - -namespace dr300 { // dr300: yes - template<typename R, typename A> void f(R (&)(A)) {} - int g(int); - void h() { f(g); } -} - -namespace dr301 { // dr301: yes - // see also dr38 - struct S; - template<typename T> void operator+(T, T); - void operator-(S, S); - - void f() { - bool a = (void(*)(S, S))operator+<S> < - (void(*)(S, S))operator+<S>; - bool b = (void(*)(S, S))operator- < - (void(*)(S, S))operator-; - bool c = (void(*)(S, S))operator+ < - (void(*)(S, S))operator-; // expected-error {{expected '>'}} - } - - template<typename T> void f() { - typename T::template operator+<int> a; // expected-error {{typename specifier refers to a non-type template}} expected-error +{{}} - // FIXME: This shouldn't say (null). - class T::template operator+<int> b; // expected-error {{identifier followed by '<' indicates a class template specialization but (null) refers to a function template}} - enum T::template operator+<int> c; // expected-error {{expected identifier}} expected-error {{does not declare anything}} - enum T::template operator+<int>::E d; // expected-error {{qualified name refers into a specialization of function template 'T::template operator +'}} expected-error {{forward reference}} - enum T::template X<int>::E e; - T::template operator+<int>::foobar(); // expected-error {{qualified name refers into a specialization of function template 'T::template operator +'}} - T::template operator+<int>(0); // ok - } - - template<typename T> class operator&<T*> {}; // expected-error +{{}} - template<typename T> class T::operator& {}; // expected-error +{{}} - template<typename T> class S::operator&<T*> {}; // expected-error +{{}} -} - -namespace dr302 { // dr302: yes - struct A { A(); ~A(); }; -#if __cplusplus < 201103L - struct B { // expected-error {{implicit default constructor for 'dr302::B' must explicitly initialize the const member 'n'}} - const int n; // expected-note {{declared here}} - A a; - } b = B(); // expected-note {{first required here}} - // Trivial default constructor C::C() is not called here. - struct C { - const int n; - } c = C(); -#else - struct B { - const int n; // expected-note {{deleted because field 'n' of const-qualified type 'const int' would not be initialized}} - A a; - } b = B(); // expected-error {{call to implicitly-deleted default constructor}} - // C::C() is called here, because even though it's trivial, it's deleted. - struct C { - const int n; // expected-note {{deleted because field 'n' of const-qualified type 'const int' would not be initialized}} - } c = C(); // expected-error {{call to implicitly-deleted default constructor}} - struct D { - const int n = 0; - } d = D(); -#endif -} - -// dr303: na - -namespace dr304 { // dr304: yes - typedef int &a; - int n = a(); // expected-error {{requires an initializer}} - - struct S { int &b; }; - int m = S().b; -#if __cplusplus < 201103L - // expected-error@-3 {{requires an initializer}} - // expected-note@-3 {{in value-initialization}} -#else - // expected-error@-5 {{deleted}} - // expected-note@-7 {{reference}} -#endif -} - -namespace dr305 { // dr305: no - struct A { - typedef A C; - }; - void f(A *a) { - struct A {}; - a->~A(); - a->~C(); - } - typedef A B; - void g(B *b) { - b->~B(); - b->~C(); - } - void h(B *b) { - struct B {}; // expected-note {{declared here}} - b->~B(); // expected-error {{does not match}} - } - - template<typename T> struct X {}; - void i(X<int>* x) { - struct X {}; - x->~X<int>(); - x->~X(); - x->~X<char>(); // expected-error {{no member named}} - } - -#if __cplusplus >= 201103L - struct Y { - template<typename T> using T1 = Y; - }; - template<typename T> using T2 = Y; - void j(Y *y) { - y->~T1<int>(); - y->~T2<int>(); - } - struct Z { - template<typename T> using T2 = T; - }; - void k(Z *z) { - // FIXME: This diagnostic is terrible. - z->~T1<int>(); // expected-error {{'T1' following the 'template' keyword does not refer to a template}} expected-error +{{}} - z->~T2<int>(); // expected-error {{no member named '~int'}} - z->~T2<Z>(); - } - - // FIXME: This is valid. - namespace Q { - template<typename A> struct R {}; - } - template<typename A> using R = Q::R<int>; - void qr(Q::R<int> x) { x.~R<char>(); } // expected-error {{no member named}} -#endif -} - -namespace dr306 { // dr306: no - // FIXME: dup 39 - // FIXME: This should be accepted. - struct A { struct B {}; }; // expected-note 2{{member}} - struct C { typedef A::B B; }; // expected-note {{member}} - struct D : A, A::B, C {}; - D::B b; // expected-error {{found in multiple base classes of different types}} -} - -// dr307: na - -namespace dr308 { // dr308: yes - // This is mostly an ABI library issue. - struct A {}; - struct B : A {}; - struct C : A {}; - struct D : B, C {}; - void f() { - try { - throw D(); - } catch (const A&) { // expected-note {{for type 'const dr308::A &'}} - // unreachable - } catch (const B&) { // expected-warning {{exception of type 'const dr308::B &' will be caught by earlier handler}} - // get here instead - } - } -} - -// dr309: dup 485 - -namespace dr311 { // dr311: yes - namespace X { namespace Y {} } - namespace X::Y {} -#if __cplusplus <= 201402L - // expected-error@-2 {{define each namespace separately}} -#endif - namespace X { - namespace X::Y {} -#if __cplusplus <= 201402L - // expected-error@-2 {{define each namespace separately}} -#endif - } - // FIXME: The diagnostics here are not very good. - namespace ::dr311::X {} // expected-error 2+{{}} // expected-warning {{extra qual}} -} - -// dr312: dup 616 - -namespace dr313 { // dr313: dup 299 c++11 - struct A { operator int() const; }; - int *p = new int[A()]; -#if __cplusplus < 201103L - // FIXME: should this be available in c++98 mode? expected-error@-2 {{extension}} -#endif -} - -namespace dr314 { // FIXME 314: dup 1710 - template<typename T> struct A { - template<typename U> struct B {}; - }; - template<typename T> struct C : public A<T>::template B<T> { - C() : A<T>::template B<T>() {} - }; -} - -// dr315: na -// dr316: sup 1004 - -namespace dr317 { // dr317: 3.5 - void f() {} // expected-note {{previous}} - inline void f(); // expected-error {{inline declaration of 'f' follows non-inline definition}} - - int g(); - int n = g(); - inline int g() { return 0; } - - int h(); - int m = h(); - int h() { return 0; } // expected-note {{previous}} - inline int h(); // expected-error {{inline declaration of 'h' follows non-inline definition}} -} - -namespace dr318 { // dr318: sup 1310 - struct A {}; - struct A::A a; -} - -namespace dr319 { // dr319: no - // FIXME: dup dr389 - // FIXME: We don't have a diagnostic for a name with linkage - // having a type without linkage. - typedef struct { - int i; - } *ps; - extern "C" void f(ps); - void g(ps); // FIXME: ill-formed, type 'ps' has no linkage - - static enum { e } a1; - enum { e2 } a2; // FIXME: ill-formed, enum type has no linkage - - enum { n1 = 1u }; - typedef int (*pa)[n1]; - pa parr; // ok, type has linkage despite using 'n1' - - template<typename> struct X {}; - - void f() { - struct A { int n; }; - extern A a; // FIXME: ill-formed - X<A> xa; - - typedef A B; - extern B b; // FIXME: ill-formed - X<B> xb; - - const int n = 1; - typedef int (*C)[n]; - extern C c; // ok - X<C> xc; - } -#if __cplusplus < 201103L - // expected-error@-12 {{uses local type 'A'}} - // expected-error@-9 {{uses local type 'A'}} -#endif -} - -namespace dr320 { // dr320: yes -#if __cplusplus >= 201103L - struct X { - constexpr X() {} - constexpr X(const X &x) : copies(x.copies + 1) {} - unsigned copies = 0; - }; - constexpr X f(X x) { return x; } - constexpr unsigned g(X x) { return x.copies; } - static_assert(f(X()).copies == g(X()) + 1, "expected one extra copy for return value"); -#endif -} - -namespace dr321 { // dr321: dup 557 - namespace N { - template<int> struct A { - template<int> struct B; - }; - template<> template<> struct A<0>::B<0>; - void f(A<0>::B<0>); - } - template<> template<> struct N::A<0>::B<0> {}; - - template<typename T> void g(T t) { f(t); } - template void g(N::A<0>::B<0>); - - namespace N { - template<typename> struct I { friend bool operator==(const I&, const I&); }; - } - N::I<int> i, j; - bool x = i == j; -} - -namespace dr322 { // dr322: yes - struct A { - template<typename T> operator T&(); - } a; - int &r = static_cast<int&>(a); - int &s = a; -} - -// dr323: no - -namespace dr324 { // dr324: yes - struct S { int n : 1; } s; // expected-note 3{{bit-field is declared here}} - int &a = s.n; // expected-error {{non-const reference cannot bind to bit-field}} - int *b = &s.n; // expected-error {{address of bit-field}} - int &c = (s.n = 0); // expected-error {{non-const reference cannot bind to bit-field}} - int *d = &(s.n = 0); // expected-error {{address of bit-field}} - int &e = true ? s.n : s.n; // expected-error {{non-const reference cannot bind to bit-field}} - int *f = &(true ? s.n : s.n); // expected-error {{address of bit-field}} - int &g = (void(), s.n); // expected-error {{non-const reference cannot bind to bit-field}} - int *h = &(void(), s.n); // expected-error {{address of bit-field}} - int *i = &++s.n; // expected-error {{address of bit-field}} -} - -namespace dr326 { // dr326: yes - struct S {}; - int test[__is_trivially_constructible(S, const S&) ? 1 : -1]; -} - -namespace dr327 { // dr327: dup 538 - struct A; - class A {}; - - class B; - struct B {}; -} - -namespace dr328 { // dr328: yes - struct A; // expected-note 3{{forward declaration}} - struct B { A a; }; // expected-error {{incomplete}} - template<typename> struct C { A a; }; // expected-error {{incomplete}} - A *p = new A[0]; // expected-error {{incomplete}} -} - -namespace dr329 { // dr329: 3.5 - struct B {}; - template<typename T> struct A : B { - friend void f(A a) { g(a); } - friend void h(A a) { g(a); } // expected-error {{undeclared}} - friend void i(B b) {} // expected-error {{redefinition}} expected-note {{previous}} - }; - A<int> a; - A<char> b; // expected-note {{instantiation}} - - void test() { - h(a); // expected-note {{instantiation}} - } -} - -namespace dr331 { // dr331: yes - struct A { - A(volatile A&); // expected-note {{candidate}} - } const a, b(a); // expected-error {{no matching constructor}} -} - -namespace dr332 { // dr332: dup 577 - void f(volatile void); // expected-error {{'void' as parameter must not have type qualifiers}} - void g(const void); // expected-error {{'void' as parameter must not have type qualifiers}} - void h(int n, volatile void); // expected-error {{'void' must be the first and only parameter}} -} - -namespace dr333 { // dr333: yes - int n = 0; - int f(int(n)); - int g((int(n))); - int h = f(g); -} - -namespace dr334 { // dr334: yes - template<typename T> void f() { - T x; - f((x, 123)); - } - struct S { - friend S operator,(S, int); - friend void f(S); - }; - template void f<S>(); -} - -// dr335: no - -namespace dr336 { // dr336: yes - namespace Pre { - template<class T1> class A { - template<class T2> class B { - template<class T3> void mf1(T3); - void mf2(); - }; - }; - template<> template<class X> class A<int>::B {}; - template<> template<> template<class T> void A<int>::B<double>::mf1(T t) {} // expected-error {{does not match}} - template<class Y> template<> void A<Y>::B<double>::mf2() {} // expected-error {{does not refer into a class}} - } - namespace Post { - template<class T1> class A { - template<class T2> class B { - template<class T3> void mf1(T3); - void mf2(); - }; - }; - template<> template<class X> class A<int>::B { - template<class T> void mf1(T); - }; - template<> template<> template<class T> void A<int>::B<double>::mf1(T t) {} - // FIXME: This diagnostic isn't very good. - template<class Y> template<> void A<Y>::B<double>::mf2() {} // expected-error {{does not refer into a class}} - } -} - -namespace dr337 { // dr337: yes - template<typename T> void f(T (*)[1]); - template<typename T> int &f(...); - - struct A { virtual ~A() = 0; }; - int &r = f<A>(0); - - // FIXME: The language rules here are completely broken. We cannot determine - // whether an incomplete type is abstract. See DR1640, which will probably - // supersede this one and remove this rule. - struct B; - int &s = f<B>(0); // expected-error {{of type 'void'}} - struct B { virtual ~B() = 0; }; -} - -namespace dr339 { // dr339: yes - template <int I> struct A { static const int value = I; }; - - char xxx(int); - char (&xxx(float))[2]; - - template<class T> A<sizeof(xxx((T)0))> f(T) {} // expected-note {{candidate}} - - void test() { - A<1> a = f(0); - A<2> b = f(0.0f); - A<3> c = f("foo"); // expected-error {{no matching function}} - } - - - char f(int); - int f(...); - - template <class T> struct conv_int { - static const bool value = sizeof(f(T())) == 1; - }; - - template <class T> bool conv_int2(A<sizeof(f(T()))> p); - - template<typename T> A<sizeof(f(T()))> make_A(); - - int a[conv_int<char>::value ? 1 : -1]; - bool b = conv_int2<char>(A<1>()); - A<1> c = make_A<char>(); -} - -namespace dr340 { // dr340: yes - struct A { A(int); }; - struct B { B(A, A, int); }; - int x, y; - B b(A(x), A(y), 3); -} - -namespace dr341 { // dr341: sup 1708 - namespace A { - int n; - extern "C" int &dr341_a = n; // expected-note {{previous}} expected-note {{declared with C language linkage here}} - } - namespace B { - extern "C" int &dr341_a = dr341_a; // expected-error {{redefinition}} - } - extern "C" void dr341_b(); // expected-note {{declared with C language linkage here}} -} -int dr341_a; // expected-error {{declaration of 'dr341_a' in global scope conflicts with declaration with C language linkage}} -int dr341_b; // expected-error {{declaration of 'dr341_b' in global scope conflicts with declaration with C language linkage}} -int dr341_c; // expected-note {{declared in global scope here}} -int dr341_d; // expected-note {{declared in global scope here}} -namespace dr341 { - extern "C" int dr341_c; // expected-error {{declaration of 'dr341_c' with C language linkage conflicts with declaration in global scope}} - extern "C" void dr341_d(); // expected-error {{declaration of 'dr341_d' with C language linkage conflicts with declaration in global scope}} - - namespace A { extern "C" int dr341_e; } // expected-note {{previous}} - namespace B { extern "C" void dr341_e(); } // expected-error {{redefinition of 'dr341_e' as different kind of symbol}} -} - -// dr342: na - -namespace dr343 { // FIXME 343: no - // FIXME: dup 1710 - template<typename T> struct A { - template<typename U> struct B {}; - }; - // FIXME: In these contexts, the 'template' keyword is optional. - template<typename T> struct C : public A<T>::B<T> { // expected-error {{use 'template'}} - C() : A<T>::B<T>() {} // expected-error {{use 'template'}} - }; -} - -namespace dr344 { // dr344: dup 1435 - struct A { inline virtual ~A(); }; - struct B { friend A::~A(); }; -} - -namespace dr345 { // dr345: yes - struct A { - struct X {}; - int X; // expected-note {{here}} - }; - struct B { - struct X {}; - }; - template <class T> void f(T t) { typename T::X x; } // expected-error {{refers to non-type member 'X'}} - void f(A a, B b) { - f(b); - f(a); // expected-note {{instantiation}} - } -} - -// dr346: na - -namespace dr347 { // dr347: yes - struct base { - struct nested; - static int n; - static void f(); - void g(); - }; - - struct derived : base {}; - - struct derived::nested {}; // expected-error {{no struct named 'nested'}} - int derived::n; // expected-error {{no member named 'n'}} - void derived::f() {} // expected-error {{does not match any}} - void derived::g() {} // expected-error {{does not match any}} -} - -// dr348: na - -namespace dr349 { // dr349: no - struct A { - template <class T> operator T ***() { - int ***p = 0; - return p; // expected-error {{cannot initialize return object of type 'const int ***' with an lvalue of type 'int ***'}} - } - }; - - // FIXME: This is valid. - A a; - const int *const *const *p1 = a; // expected-note {{in instantiation of}} - - struct B { - template <class T> operator T ***() { - const int ***p = 0; - return p; - } - }; - - // FIXME: This is invalid. - B b; - const int *const *const *p2 = b; -} - -// dr351: na - -namespace dr352 { // dr352: yes - namespace example1 { - namespace A { - enum E {}; - template<typename R, typename A> void foo(E, R (*)(A)); // expected-note 2{{couldn't infer template argument 'R'}} - } - - template<typename T> void arg(T); - template<typename T> int arg(T) = delete; // expected-note {{here}} expected-error 0-1{{extension}} - - void f(A::E e) { - foo(e, &arg); // expected-error {{no matching function}} - - using A::foo; - foo<int, int>(e, &arg); // expected-error {{deleted}} - } - - int arg(int); - - void g(A::E e) { - foo(e, &arg); // expected-error {{no matching function}} - - using A::foo; - foo<int, int>(e, &arg); // ok, uses non-template - } - } - - namespace contexts { - template<int I> void f1(int (&)[I]); - template<int I> void f2(int (&)[I+1]); // expected-note {{couldn't infer}} - template<int I> void f3(int (&)[I+1], int (&)[I]); - void f() { - int a[4]; - int b[3]; - f1(a); - f2(a); // expected-error {{no matching function}} - f3(a, b); - } - - template<int I> struct S {}; - template<int I> void g1(S<I>); - template<int I> void g2(S<I+1>); // expected-note {{couldn't infer}} - template<int I> void g3(S<I+1>, S<I>); - void g() { - S<4> a; - S<3> b; - g1(a); - g2(a); // expected-error {{no matching function}} - g3(a, b); - } - - template<typename T> void h1(T = 0); // expected-note {{couldn't infer}} - template<typename T> void h2(T, T = 0); - void h() { - h1(); // expected-error {{no matching function}} - h1(0); - h1<int>(); - h2(0); - } - - template<typename T> int tmpl(T); - template<typename R, typename A> void i1(R (*)(A)); // expected-note 3{{couldn't infer}} - template<typename R, typename A> void i2(R, A, R (*)(A)); // expected-note {{not viable}} - void i() { - extern int single(int); - i1(single); - i2(0, 0, single); - - extern int ambig(float), ambig(int); - i1(ambig); // expected-error {{no matching function}} - i2(0, 0, ambig); - - extern void no_match(float), no_match(int); - i1(no_match); // expected-error {{no matching function}} - i2(0, 0, no_match); // expected-error {{no matching function}} - - i1(tmpl); // expected-error {{no matching function}} - i2(0, 0, tmpl); - } - } - - template<typename T> struct is_int; - template<> struct is_int<int> {}; - - namespace example2 { - template<typename T> int f(T (*p)(T)) { is_int<T>(); } - int g(int); - int g(char); - int i = f(g); - } - - namespace example3 { - template<typename T> int f(T, T (*p)(T)) { is_int<T>(); } - int g(int); - char g(char); - int i = f(1, g); - } - - namespace example4 { - template <class T> int f(T, T (*p)(T)) { is_int<T>(); } - char g(char); - template <class T> T g(T); - int i = f(1, g); - } - - namespace example5 { - template<int I> class A {}; - template<int I> void g(A<I+1>); // expected-note {{couldn't infer}} - template<int I> void f(A<I>, A<I+1>); - void h(A<1> a1, A<2> a2) { - g(a1); // expected-error {{no matching function}} - g<0>(a1); - f(a1, a2); - } - } -} - -// dr353 needs an IRGen test. - -namespace dr354 { // dr354: yes c++11 - // FIXME: Should we allow this in C++98 too? - struct S {}; - - template<int*> struct ptr {}; // expected-note 0-4{{here}} - ptr<0> p0; - ptr<(int*)0> p1; - ptr<(float*)0> p2; - ptr<(int S::*)0> p3; -#if __cplusplus < 201103L - // expected-error@-5 {{does not refer to any decl}} - // expected-error@-5 {{does not refer to any decl}} - // expected-error@-5 {{does not refer to any decl}} - // expected-error@-5 {{does not refer to any decl}} -#elif __cplusplus <= 201402L - // expected-error@-10 {{must be cast}} - // ok - // expected-error@-10 {{does not match}} - // expected-error@-10 {{does not match}} -#else - // expected-error@-15 {{conversion from 'int' to 'int *' is not allowed}} - // ok - // expected-error@-15 {{'float *' is not implicitly convertible to 'int *'}} - // expected-error@-15 {{'int dr354::S::*' is not implicitly convertible to 'int *'}} -#endif - - template<int*> int both(); - template<int> int both(); - int b0 = both<0>(); - int b1 = both<(int*)0>(); -#if __cplusplus < 201103L - // expected-error@-2 {{no matching function}} - // expected-note@-6 {{candidate}} - // expected-note@-6 {{candidate}} -#endif - - template<int S::*> struct ptr_mem {}; // expected-note 0-4{{here}} - ptr_mem<0> m0; - ptr_mem<(int S::*)0> m1; - ptr_mem<(float S::*)0> m2; - ptr_mem<(int *)0> m3; -#if __cplusplus < 201103L - // expected-error@-5 {{cannot be converted}} - // expected-error@-5 {{is not a pointer to member constant}} - // expected-error@-5 {{cannot be converted}} - // expected-error@-5 {{cannot be converted}} -#elif __cplusplus <= 201402L - // expected-error@-10 {{must be cast}} - // ok - // expected-error@-10 {{does not match}} - // expected-error@-10 {{does not match}} -#else - // expected-error@-15 {{conversion from 'int' to 'int dr354::S::*' is not allowed}} - // ok - // expected-error@-15 {{'float dr354::S::*' is not implicitly convertible to 'int dr354::S::*'}} - // expected-error@-15 {{'int *' is not implicitly convertible to 'int dr354::S::*'}} -#endif -} - -struct dr355_S; // dr355: yes -struct ::dr355_S {}; // expected-warning {{extra qualification}} -namespace dr355 { struct ::dr355_S s; } - -// dr356: na - -namespace dr357 { // dr357: yes - template<typename T> struct A { - void f() const; // expected-note {{const qualified}} - }; - template<typename T> void A<T>::f() {} // expected-error {{does not match}} - - struct B { - template<typename T> void f(); - }; - template<typename T> void B::f() const {} // expected-error {{does not match}} -} - -namespace dr358 { // dr358: yes - extern "C" void dr358_f(); - namespace N { - int var; - extern "C" void dr358_f() { var = 10; } - } -} - -namespace dr359 { // dr359: yes - // Note, the example in the DR is wrong; it doesn't contain an anonymous - // union. - struct E { - union { - struct { - int x; - } s; - } v; - - union { - struct { // expected-error {{extension}} - int x; - } s; - - struct S { // expected-error {{types cannot be declared in an anonymous union}} - int x; - } t; - - union { // expected-error {{extension}} - int u; - }; - }; - }; -} - -// dr362: na -// dr363: na - -namespace dr364 { // dr364: yes - struct S { - static void f(int); - void f(char); - }; - - void g() { - S::f('a'); // expected-error {{call to non-static}} - S::f(0); - } -} - -#if "foo" // expected-error {{invalid token}} dr366: yes -#endif - -namespace dr367 { // dr367: yes - // FIXME: These diagnostics are terrible. Don't diagnose an ill-formed global - // array as being a VLA! - int a[true ? throw 0 : 4]; // expected-error 2{{variable length array}} - int b[true ? 4 : throw 0]; - int c[true ? *new int : 4]; // expected-error 2{{variable length array}} - int d[true ? 4 : *new int]; -#if __cplusplus < 201103L - // expected-error@-4 {{variable length array}} expected-error@-4 {{constant expression}} - // expected-error@-3 {{variable length array}} expected-error@-3 {{constant expression}} -#endif -} - -namespace dr368 { // dr368: yes - template<typename T, T> struct S {}; // expected-note {{here}} - template<typename T> int f(S<T, T()> *); // expected-error {{function type}} - //template<typename T> int g(S<T, (T())> *); // FIXME: crashes clang - template<typename T> int g(S<T, true ? T() : T()> *); // expected-note {{cannot have type 'dr368::X'}} - struct X {}; - int n = g<X>(0); // expected-error {{no matching}} -} - -// dr370: na - -namespace dr372 { // dr372: no - namespace example1 { - template<typename T> struct X { - protected: - typedef T Type; // expected-note 2{{protected}} - }; - template<typename T> struct Y {}; - - // FIXME: These two are valid; deriving from T1<T> gives Z1 access to - // the protected member T1<T>::Type. - template<typename T, - template<typename> class T1, - template<typename> class T2> struct Z1 : - T1<T>, - T2<typename T1<T>::Type> {}; // expected-error {{protected}} - - template<typename T, - template<typename> class T1, - template<typename> class T2> struct Z2 : - T2<typename T1<T>::Type>, // expected-error {{protected}} - T1<T> {}; - - Z1<int, X, Y> z1; // expected-note {{instantiation of}} - Z2<int, X, Y> z2; // expected-note {{instantiation of}} - } - - namespace example2 { - struct X { - private: - typedef int Type; // expected-note {{private}} - }; - template<typename T> struct A { - typename T::Type t; // expected-error {{private}} - }; - A<X> ax; // expected-note {{instantiation of}} - } - - namespace example3 { - struct A { - protected: - typedef int N; // expected-note 2{{protected}} - }; - - template<typename T> struct B {}; - template<typename U> struct C : U, B<typename U::N> {}; // expected-error {{protected}} - template<typename U> struct D : B<typename U::N>, U {}; // expected-error {{protected}} - - C<A> x; // expected-note {{instantiation of}} - D<A> y; // expected-note {{instantiation of}} - } - - namespace example4 { - class A { - class B {}; - friend class X; - }; - - struct X : A::B { - A::B mx; - class Y { - A::B my; - }; - }; - } -} - -namespace dr373 { // dr373: no - // FIXME: This is valid. - namespace X { int dr373; } // expected-note 2{{here}} - struct dr373 { // expected-note {{here}} - void f() { - using namespace dr373::X; // expected-error {{no namespace named 'X' in 'dr373::dr373'}} - int k = dr373; // expected-error {{does not refer to a value}} - - namespace Y = dr373::X; // expected-error {{no namespace named 'X' in 'dr373::dr373'}} - k = Y::dr373; - } - }; -} - -namespace dr374 { // dr374: yes c++11 - namespace N { - template<typename T> void f(); - template<typename T> struct A { void f(); }; - } - template<> void N::f<char>() {} - template<> void N::A<char>::f() {} - template<> struct N::A<int> {}; -#if __cplusplus < 201103L - // expected-error@-4 {{extension}} expected-note@-7 {{here}} - // expected-error@-4 {{extension}} expected-note@-7 {{here}} - // expected-error@-4 {{extension}} expected-note@-8 {{here}} -#endif -} - -// dr375: dup 345 -// dr376: na - -namespace dr377 { // dr377: yes - enum E { // expected-error {{enumeration values exceed range of largest integer}} - a = -__LONG_LONG_MAX__ - 1, // expected-error 0-1{{extension}} - b = 2 * (unsigned long long)__LONG_LONG_MAX__ // expected-error 0-2{{extension}} - }; -} - -// dr378: dup 276 -// dr379: na - -namespace dr381 { // dr381: yes - struct A { - int a; - }; - struct B : virtual A {}; - struct C : B {}; - struct D : B {}; - struct E : public C, public D {}; - struct F : public A {}; - void f() { - E e; - e.B::a = 0; // expected-error {{ambiguous conversion}} - F f; - f.A::a = 1; - } -} - -namespace dr382 { // dr382: yes c++11 - // FIXME: Should we allow this in C++98 mode? - struct A { typedef int T; }; - typename A::T t; - typename dr382::A a; -#if __cplusplus < 201103L - // expected-error@-3 {{occurs outside of a template}} - // expected-error@-3 {{occurs outside of a template}} -#endif - typename A b; // expected-error {{expected a qualified name}} -} - -namespace dr383 { // dr383: yes - struct A { A &operator=(const A&); }; - struct B { ~B(); }; - union C { C &operator=(const C&); }; - union D { ~D(); }; - int check[(__is_pod(A) || __is_pod(B) || __is_pod(C) || __is_pod(D)) ? -1 : 1]; -} - -namespace dr384 { // dr384: yes - namespace N1 { - template<typename T> struct Base {}; - template<typename T> struct X { - struct Y : public Base<T> { - Y operator+(int) const; - }; - Y f(unsigned i) { return Y() + i; } - }; - } - - namespace N2 { - struct Z {}; - template<typename T> int *operator+(T, unsigned); - } - - int main() { - N1::X<N2::Z> v; - v.f(0); - } -} - -namespace dr385 { // dr385: yes - struct A { protected: void f(); }; - struct B : A { using A::f; }; - struct C : A { void g(B b) { b.f(); } }; - void h(B b) { b.f(); } - - struct D { int n; }; // expected-note {{member}} - struct E : protected D {}; // expected-note 2{{protected}} - struct F : E { friend int i(E); }; - int i(E e) { return e.n; } // expected-error {{protected base}} expected-error {{protected member}} -} - -namespace dr387 { // dr387: yes - namespace old { - template<typename T> class number { - number(int); // expected-note 2{{here}} - friend number gcd(number &x, number &y) {} - }; - - void g() { - number<double> a(3), b(4); // expected-error 2{{private}} - a = gcd(a, b); - b = gcd(3, 4); // expected-error {{undeclared}} - } - } - - namespace newer { - template <typename T> class number { - public: - number(int); - friend number gcd(number x, number y) { return 0; } - }; - - void g() { - number<double> a(3), b(4); - a = gcd(a, b); - b = gcd(3, 4); // expected-error {{undeclared}} - } - } -} - -// FIXME: dr388 needs codegen test - -namespace dr389 { // dr389: no - struct S { - typedef struct {} A; - typedef enum {} B; - typedef struct {} const C; // expected-note 0-2{{here}} - typedef enum {} const D; // expected-note 0-1{{here}} - }; - template<typename> struct T {}; - - struct WithLinkage1 {}; - enum WithLinkage2 {}; - typedef struct {} *WithLinkage3a, WithLinkage3b; - typedef enum {} WithLinkage4a, *WithLinkage4b; - typedef S::A WithLinkage5; - typedef const S::B WithLinkage6; - typedef int WithLinkage7; - typedef void (*WithLinkage8)(WithLinkage2 WithLinkage1::*, WithLinkage5 *); - typedef T<WithLinkage5> WithLinkage9; - - typedef struct {} *WithoutLinkage1; // expected-note 0-1{{here}} - typedef enum {} const WithoutLinkage2; // expected-note 0-1{{here}} - // These two types don't have linkage even though they are externally visible - // and the ODR requires them to be merged across TUs. - typedef S::C WithoutLinkage3; - typedef S::D WithoutLinkage4; - typedef void (*WithoutLinkage5)(int (WithoutLinkage3::*)(char)); - -#if __cplusplus >= 201103L - // This has linkage even though its template argument does not. - // FIXME: This is probably a defect. - typedef T<WithoutLinkage1> WithLinkage10; -#else - typedef int WithLinkage10; // dummy - - typedef T<WithLinkage1> GoodArg1; - typedef T<WithLinkage2> GoodArg2; - typedef T<WithLinkage3a> GoodArg3a; - typedef T<WithLinkage3b> GoodArg3b; - typedef T<WithLinkage4a> GoodArg4a; - typedef T<WithLinkage4b> GoodArg4b; - typedef T<WithLinkage5> GoodArg5; - typedef T<WithLinkage6> GoodArg6; - typedef T<WithLinkage7> GoodArg7; - typedef T<WithLinkage8> GoodArg8; - typedef T<WithLinkage9> GoodArg9; - - typedef T<WithoutLinkage1> BadArg1; // expected-error{{template argument uses}} - typedef T<WithoutLinkage2> BadArg2; // expected-error{{template argument uses}} - typedef T<WithoutLinkage3> BadArg3; // expected-error{{template argument uses}} - typedef T<WithoutLinkage4> BadArg4; // expected-error{{template argument uses}} - typedef T<WithoutLinkage5> BadArg5; // expected-error{{template argument uses}} -#endif - - extern WithLinkage1 withLinkage1; - extern WithLinkage2 withLinkage2; - extern WithLinkage3a withLinkage3a; - extern WithLinkage3b withLinkage3b; - extern WithLinkage4a withLinkage4a; - extern WithLinkage4b withLinkage4b; - extern WithLinkage5 withLinkage5; - extern WithLinkage6 withLinkage6; - extern WithLinkage7 withLinkage7; - extern WithLinkage8 withLinkage8; - extern WithLinkage9 withLinkage9; - extern WithLinkage10 withLinkage10; - - // FIXME: These are all ill-formed. - extern WithoutLinkage1 withoutLinkage1; - extern WithoutLinkage2 withoutLinkage2; - extern WithoutLinkage3 withoutLinkage3; - extern WithoutLinkage4 withoutLinkage4; - extern WithoutLinkage5 withoutLinkage5; - - // OK, extern "C". - extern "C" { - extern WithoutLinkage1 dr389_withoutLinkage1; - extern WithoutLinkage2 dr389_withoutLinkage2; - extern WithoutLinkage3 dr389_withoutLinkage3; - extern WithoutLinkage4 dr389_withoutLinkage4; - extern WithoutLinkage5 dr389_withoutLinkage5; - } - - // OK, defined. - WithoutLinkage1 withoutLinkageDef1; - WithoutLinkage2 withoutLinkageDef2 = WithoutLinkage2(); - WithoutLinkage3 withoutLinkageDef3 = {}; - WithoutLinkage4 withoutLinkageDef4 = WithoutLinkage4(); - WithoutLinkage5 withoutLinkageDef5; - - void use(const void *); - void use_all() { - use(&withLinkage1); use(&withLinkage2); use(&withLinkage3a); use(&withLinkage3b); - use(&withLinkage4a); use(&withLinkage4b); use(&withLinkage5); use(&withLinkage6); - use(&withLinkage7); use(&withLinkage8); use(&withLinkage9); use(&withLinkage10); - - use(&withoutLinkage1); use(&withoutLinkage2); use(&withoutLinkage3); - use(&withoutLinkage4); use(&withoutLinkage5); - - use(&dr389_withoutLinkage1); use(&dr389_withoutLinkage2); - use(&dr389_withoutLinkage3); use(&dr389_withoutLinkage4); - use(&dr389_withoutLinkage5); - - use(&withoutLinkageDef1); use(&withoutLinkageDef2); use(&withoutLinkageDef3); - use(&withoutLinkageDef4); use(&withoutLinkageDef5); - } - - void local() { - // FIXME: This is ill-formed. - extern WithoutLinkage1 withoutLinkageLocal; - } -} - -namespace dr390 { // dr390: yes - template<typename T> - struct A { - A() { f(); } // expected-warning {{call to pure virt}} - virtual void f() = 0; // expected-note {{here}} - virtual ~A() = 0; - }; - template<typename T> A<T>::~A() { T::error; } // expected-error {{cannot be used prior to}} - template<typename T> void A<T>::f() { T::error; } // ok, not odr-used - struct B : A<int> { // expected-note 2{{in instantiation of}} - void f() {} - } b; -} - -namespace dr391 { // dr391: yes c++11 - // FIXME: Should this apply to C++98 too? - class A { A(const A&); }; // expected-note 0-1{{here}} - A fa(); - const A &a = fa(); -#if __cplusplus < 201103L - // expected-error@-2 {{C++98 requires an accessible copy constructor}} -#endif - - struct B { B(const B&) = delete; }; // expected-error 0-1{{extension}} expected-note 0-1{{here}} - B fb(); - const B &b = fb(); -#if __cplusplus < 201103L - // expected-error@-2 {{deleted}} -#endif - - template<typename T> - struct C { - C(const C&) { T::error; } - }; - C<int> fc(); - const C<int> &c = fc(); -} - -// dr392 FIXME write codegen test -// dr394: na - -namespace dr395 { // dr395: yes - struct S { - template <typename T, int N>(&operator T())[N]; // expected-error {{cannot specify any part of a return type}} - template <typename T, int N> operator(T (&)[N])(); // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error +{{}} - template <typename T> operator T *() const { return 0; } - template <typename T, typename U> operator T U::*() const { return 0; } - template <typename T, typename U> operator T (U::*)()() const { return 0; } // expected-error +{{}} - }; - - struct null1_t { - template <class T, class U> struct ptr_mem_fun_t { - typedef T (U::*type)(); - }; - - template <class T, class U> - operator typename ptr_mem_fun_t<T, U>::type() const { // expected-note {{couldn't infer}} - return 0; - } - } null1; - int (S::*p)() = null1; // expected-error {{no viable conversion}} - - template <typename T> using id = T; // expected-error 0-1{{extension}} - - struct T { - template <typename T, int N> operator id<T[N]> &(); - template <typename T, typename U> operator id<T (U::*)()>() const; - }; - - struct null2_t { - template<class T, class U> using ptr_mem_fun_t = T (U::*)(); // expected-error 0-1{{extension}} - template<class T, class U> operator ptr_mem_fun_t<T, U>() const { return 0; }; - } null2; - int (S::*q)() = null2; -} - -namespace dr396 { // dr396: yes - void f() { - auto int a(); // expected-error {{storage class on function}} - int (i); // expected-note {{previous}} - auto int (i); // expected-error {{redefinition}} -#if __cplusplus >= 201103L - // expected-error@-4 {{'auto' storage class}} expected-error@-2 {{'auto' storage class}} -#endif - } -} - -// dr397: sup 1823 - -namespace dr398 { // dr398: yes - namespace example1 { - struct S { - static int const I = 42; - }; - template <int N> struct X {}; - template <typename T> void f(X<T::I> *) {} - template <typename T> void f(X<T::J> *) {} - void foo() { f<S>(0); } - } - - namespace example2 { - template <int I> struct X {}; - template <template <class T> class> struct Z {}; - template <class T> void f(typename T::Y *) {} // expected-note 2{{substitution failure}} - template <class T> void g(X<T::N> *) {} // expected-note {{substitution failure}} - template <class T> void h(Z<T::template TT> *) {} // expected-note {{substitution failure}} - struct A {}; - struct B { - int Y; - }; - struct C { - typedef int N; - }; - struct D { - typedef int TT; - }; - - void test() { - f<A>(0); // expected-error {{no matching function}} - f<B>(0); // expected-error {{no matching function}} - g<C>(0); // expected-error {{no matching function}} - h<D>(0); // expected-error {{no matching function}} - } - } -} Index: lib/FrontendTool/ExecuteCompilerInvocation.cpp =================================================================== --- lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -185,14 +185,8 @@ } // Load any requested plugins. - for (unsigned i = 0, - e = Clang->getFrontendOpts().Plugins.size(); i != e; ++i) { - const std::string &Path = Clang->getFrontendOpts().Plugins[i]; - std::string Error; - if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error)) - Clang->getDiagnostics().Report(diag::err_fe_unable_to_load_plugin) - << Path << Error; - } + Clang->loadPlugins(); + // Honor -mllvm. // Index: lib/Frontend/CompilerInstance.cpp =================================================================== --- lib/Frontend/CompilerInstance.cpp +++ lib/Frontend/CompilerInstance.cpp @@ -45,6 +45,7 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/DynamicLibrary.h" #include <sys/stat.h> #include <system_error> #include <time.h> @@ -1752,3 +1753,15 @@ return false; } void CompilerInstance::resetAndLeakSema() { BuryPointer(takeSema()); } + +void +CompilerInstance::loadPlugins(){ + // Load any requested plugins. + for (unsigned i = 0, e = getFrontendOpts().Plugins.size(); i != e; ++i) { + const std::string &Path = getFrontendOpts().Plugins[i]; + std::string Error; + if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error)) + getDiagnostics().Report(diag::err_fe_unable_to_load_plugin) + << Path << Error; + } +} Index: lib/Frontend/ASTUnit.cpp =================================================================== --- lib/Frontend/ASTUnit.cpp +++ lib/Frontend/ASTUnit.cpp @@ -1135,6 +1135,8 @@ llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction> ActCleanup(Act.get()); + Clang->loadPlugins(); + if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) goto error; Index: include/clang/Frontend/CompilerInstance.h =================================================================== --- include/clang/Frontend/CompilerInstance.h +++ include/clang/Frontend/CompilerInstance.h @@ -779,6 +779,9 @@ void addDependencyCollector(std::shared_ptr<DependencyCollector> Listener) { DependencyCollectors.push_back(std::move(Listener)); } + + /// load plugins that were added by -load + void loadPlugins(); }; } // end namespace clang
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits