diff options
author | David Blaikie <dblaikie@gmail.com> | 2011-12-13 08:03:36 +0000 |
---|---|---|
committer | David Blaikie <dblaikie@gmail.com> | 2011-12-13 08:03:36 +0000 |
commit | df512bfbc4b8c00202ea7a8c900c59ec55890676 (patch) | |
tree | bd01bd563b330a89de589e462f6efeb7a1d15c48 | |
parent | c1c5f27c64dfc3332d53ad30e44d626e4f9afac3 (diff) |
Disallow decltype in qualified declarator-ids.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146480 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 10 | ||||
-rw-r--r-- | test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp | 26 | ||||
-rw-r--r-- | test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp | 4 |
4 files changed, 38 insertions, 4 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 56d5348275..0ad0513d49 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1144,6 +1144,8 @@ def err_cannot_determine_declared_type_of_overloaded_function : Error< def warn_cxx98_compat_decltype : Warning< "'decltype' type specifier is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; +def err_decltype_in_declarator : Error< + "'decltype' cannot be used to name a declaration">; // C++11 auto def warn_cxx98_compat_auto_type_specifier : Warning< diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index bd2e639eab..63a1b8034e 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3203,6 +3203,16 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, (S->getFlags() & Scope::TemplateParamScope) != 0) S = S->getParent(); + if (NestedNameSpecifierLoc SpecLoc = + D.getCXXScopeSpec().getWithLocInContext(Context)) { + while (SpecLoc.getPrefix()) + SpecLoc = SpecLoc.getPrefix(); + if (dyn_cast_or_null<DecltypeType>( + SpecLoc.getNestedNameSpecifier()->getAsType())) + Diag(SpecLoc.getBeginLoc(), diag::err_decltype_in_declarator) + << SpecLoc.getTypeLoc().getSourceRange(); + } + DeclContext *DC = CurContext; if (D.getCXXScopeSpec().isInvalid()) D.setInvalidType(); diff --git a/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp new file mode 100644 index 0000000000..8dcbaf8381 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// The nested-name-specifier of a qualified declarator-id shall not begin with a decltype-specifier. +class foo { + static int i; + void func(); +}; + +int decltype(foo())::i; // expected-error{{'decltype' cannot be used to name a declaration}} +void decltype(foo())::func() { // expected-error{{'decltype' cannot be used to name a declaration}} +} + + +template<typename T> +class tfoo { + static int i; + void func(); +}; + +template<typename T> +int decltype(tfoo<T>())::i; // expected-error{{'decltype' cannot be used to name a declaration}} \ + expected-error{{nested name specifier 'decltype(tfoo<T>())::' for declaration does not refer into a class, class template or class template partial specialization}} +template<typename T> +void decltype(tfoo<T>())::func() { // expected-error{{'decltype' cannot be used to name a declaration}} \ + expected-error{{nested name specifier 'decltype(tfoo<T>())::' for declaration does not refer into a class, class template or class template partial specialization}} +} diff --git a/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp b/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp index 80ae67a97c..5b3a004056 100644 --- a/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp @@ -28,10 +28,6 @@ namespace PR10127 { int (decltype(outer())::middle::inner::*p)()); }; - int decltype(outer::middle())::inner::func() { - return 0; - } - decltype(outer::middle::inner()) a; void scope() { a.decltype(outer::middle())::mfunc(); // expected-error{{'PR10127::outer::middle::mfunc' is not a member of class 'decltype(outer::middle::inner())'}} |