[cfe-commits] r80332 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDeclCXX.cpp test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
Anders Carlsson
andersca at mac.com
Thu Aug 27 20:16:11 PDT 2009
Author: andersca
Date: Thu Aug 27 22:16:11 2009
New Revision: 80332
URL: http://llvm.org/viewvc/llvm-project?rev=80332&view=rev
Log:
Many improvements to using declarations.
Added:
cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp
cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=80332&r1=80331&r2=80332&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Aug 27 22:16:11 2009
@@ -92,13 +92,19 @@
"use of out-of-scope declaration of %0">;
def err_inline_non_function : Error<
"'inline' can only appear on functions">;
+
+// C++ using declarations
def err_using_requires_qualname : Error<
"using declaration requires a qualified name">;
def err_using_typename_non_type : Error<
"'typename' keyword used on a non-type">;
def err_using_dependent_unsupported : Error<
"dependent using declaration not supported yet">;
-
+def err_using_decl_nested_name_specifier_is_not_a_base_class : Error<
+ "using declaration refers into %0, which is not a base class of %1">;
+def err_using_decl_refers_to_class_member : Error<
+ "using declaration refers to class member">;
+
def err_invalid_thread : Error<
"'__thread' is only allowed on variable declarations">;
def err_thread_non_global : Error<
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=80332&r1=80331&r2=80332&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Aug 27 22:16:11 2009
@@ -2094,13 +2094,13 @@
Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
- SourceLocation UsingLoc,
- const CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *TargetName,
- OverloadedOperatorKind Op,
- AttributeList *AttrList,
- bool IsTypeName) {
+ SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *TargetName,
+ OverloadedOperatorKind Op,
+ AttributeList *AttrList,
+ bool IsTypeName) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
assert((TargetName || Op) && "Invalid TargetName.");
assert(IdentLoc.isValid() && "Invalid TargetName location.");
@@ -2118,25 +2118,74 @@
if (isUnknownSpecialization(SS)) {
Diag(IdentLoc, diag::err_using_dependent_unsupported);
delete AttrList;
- return DeclPtrTy::make((UsingDecl*)0);
+ return DeclPtrTy();
}
- // Lookup target name.
- LookupResult R = LookupParsedName(S, &SS, Name, LookupOrdinaryName, false);
+ if (SS.isEmpty()) {
+ Diag(IdentLoc, diag::err_using_requires_qualname);
+ return DeclPtrTy();
+ }
+
+ NestedNameSpecifier *NNS =
+ static_cast<NestedNameSpecifier *>(SS.getScopeRep());
- if (NamedDecl *NS = R) {
- if (IsTypeName && !isa<TypeDecl>(NS)) {
- Diag(IdentLoc, diag::err_using_typename_non_type);
- }
- UsingAlias = UsingDecl::Create(Context, CurContext, IdentLoc, SS.getRange(),
- NS->getLocation(), UsingLoc, NS,
- static_cast<NestedNameSpecifier *>(SS.getScopeRep()),
- IsTypeName);
- PushOnScopeChains(UsingAlias, S);
+ DeclContext *LookupContext = 0;
+
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) {
+ // C++0x N2914 [namespace.udecl]p3:
+ // A using-declaration used as a member-declaration shall refer to a member
+ // of a base class of the class being defined, shall refer to a member of an
+ // anonymous union that is a member of a base class of the class being
+ // defined, or shall refer to an enumerator for an enumeration type that is
+ // a member of a base class of the class being defined.
+ const Type *Ty = NNS->getAsType();
+ if (!Ty || !IsDerivedFrom(Context.getTagDeclType(RD), QualType(Ty, 0))) {
+ Diag(SS.getRange().getBegin(),
+ diag::err_using_decl_nested_name_specifier_is_not_a_base_class)
+ << NNS << RD->getDeclName();
+ return DeclPtrTy();
+ }
+
+ LookupContext = cast<RecordType>(Ty)->getDecl();
} else {
- Diag(IdentLoc, diag::err_using_requires_qualname) << SS.getRange();
+ // C++0x N2914 [namespace.udecl]p8:
+ // A using-declaration for a class member shall be a member-declaration.
+ if (NNS->getKind() == NestedNameSpecifier::TypeSpec) {
+ Diag(IdentLoc, diag::err_using_decl_refers_to_class_member)
+ << SS.getRange();
+ return DeclPtrTy();
+ }
+
+ // C++0x N2914 [namespace.udecl]p9:
+ // In a using-declaration, a prefix :: refers to the global namespace.
+ if (NNS->getKind() == NestedNameSpecifier::Global)
+ LookupContext = Context.getTranslationUnitDecl();
+ else
+ LookupContext = NNS->getAsNamespace();
}
+
+ // Lookup target name.
+ LookupResult R = LookupQualifiedName(LookupContext,
+ Name, LookupOrdinaryName);
+
+ if (!R) {
+ Diag(IdentLoc, diag::err_typecheck_no_member) << Name << SS.getRange();
+ return DeclPtrTy();
+ }
+
+ NamedDecl *ND = R.getAsDecl();
+
+ if (IsTypeName && !isa<TypeDecl>(ND)) {
+ Diag(IdentLoc, diag::err_using_typename_non_type);
+ return DeclPtrTy();
+ }
+
+ UsingAlias =
+ UsingDecl::Create(Context, CurContext, IdentLoc, SS.getRange(),
+ ND->getLocation(), UsingLoc, ND, NNS, IsTypeName);
+ PushOnScopeChains(UsingAlias, S);
+
// FIXME: We ignore attributes for now.
delete AttrList;
return DeclPtrTy::make(UsingAlias);
Added: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp?rev=80332&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp (added)
+++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp Thu Aug 27 22:16:11 2009
@@ -0,0 +1,20 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+// C++0x N2914.
+
+struct B {
+ void f(char);
+ void g(char);
+ enum E { e };
+ union { int x; };
+};
+
+class C {
+ int g();
+};
+
+class D2 : public B {
+ using B::f;
+ using B::e;
+ using B::x;
+ using C::g; // expected-error{{using declaration refers into 'C::', which is not a base class of 'D2'}}
+};
Added: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp?rev=80332&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp (added)
+++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp Thu Aug 27 22:16:11 2009
@@ -0,0 +1,15 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+// C++0x N2914.
+
+struct X {
+ int i;
+ static int a;
+};
+
+using X::i; // expected-error{{error: using declaration refers to class member}}
+using X::s; // expected-error{{error: using declaration refers to class member}}
+
+void f() {
+ using X::i; // expected-error{{error: using declaration refers to class member}}
+ using X::s; // expected-error{{error: using declaration refers to class member}}
+}
More information about the cfe-commits
mailing list