[cfe-commits] r134479 - in /cfe/trunk: include/clang/AST/NestedNameSpecifier.h include/clang/Sema/DeclSpec.h lib/Sema/DeclSpec.cpp lib/Sema/SemaCXXScopeSpec.cpp test/SemaCXX/enum-scoped.cpp
John McCall
rjmccall at apple.com
Tue Jul 5 23:57:57 PDT 2011
Author: rjmccall
Date: Wed Jul 6 01:57:57 2011
New Revision: 134479
URL: http://llvm.org/viewvc/llvm-project?rev=134479&view=rev
Log:
Fixed enum types can be complete without actually being valid to use
as scope specifiers; diagnose the attempt, rather than letting it go
to an assert. The rest of PR10264.
Modified:
cfe/trunk/include/clang/AST/NestedNameSpecifier.h
cfe/trunk/include/clang/Sema/DeclSpec.h
cfe/trunk/lib/Sema/DeclSpec.cpp
cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
cfe/trunk/test/SemaCXX/enum-scoped.cpp
Modified: cfe/trunk/include/clang/AST/NestedNameSpecifier.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/NestedNameSpecifier.h?rev=134479&r1=134478&r2=134479&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/NestedNameSpecifier.h (original)
+++ cfe/trunk/include/clang/AST/NestedNameSpecifier.h Wed Jul 6 01:57:57 2011
@@ -439,6 +439,14 @@
/// copied.
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
+ /// \brief Retrieve a nested-name-specifier with location
+ /// information based on the information in this builder. This loc
+ /// will contain references to the builder's internal data and may
+ /// be invalidated by any change to the builder.
+ NestedNameSpecifierLoc getTemporary() const {
+ return NestedNameSpecifierLoc(Representation, Buffer);
+ }
+
/// \brief Clear out this builder, and prepare it to build another
/// nested-name-specifier with source-location information.
void Clear() {
Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=134479&r1=134478&r2=134479&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Wed Jul 6 01:57:57 2011
@@ -154,6 +154,12 @@
/// copied.
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
+ /// \brief Retrieve the location of the name in the last qualifier
+ /// in this nested name specifier. For example:
+ /// ::foo::bar<0>::
+ /// ^~~
+ SourceLocation getLastQualifierNameLoc() const;
+
/// No scope specifier.
bool isEmpty() const { return !Range.isValid(); }
/// A scope specifier is present, but may be valid or invalid.
Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=134479&r1=134478&r2=134479&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Sema/DeclSpec.cpp Wed Jul 6 01:57:57 2011
@@ -126,6 +126,12 @@
Builder.Adopt(Other);
}
+SourceLocation CXXScopeSpec::getLastQualifierNameLoc() const {
+ if (!Builder.getRepresentation())
+ return SourceLocation();
+ return Builder.getTemporary().getLocalBeginLoc();
+}
+
NestedNameSpecifierLoc
CXXScopeSpec::getWithLocInContext(ASTContext &Context) const {
if (!Builder.getRepresentation())
Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=134479&r1=134478&r2=134479&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Wed Jul 6 01:57:57 2011
@@ -211,25 +211,40 @@
DeclContext *DC) {
assert(DC != 0 && "given null context");
- if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
+ if (TagDecl *tag = dyn_cast<TagDecl>(DC)) {
// If this is a dependent type, then we consider it complete.
- if (Tag->isDependentContext())
+ if (tag->isDependentContext())
return false;
// If we're currently defining this type, then lookup into the
// type is okay: don't complain that it isn't complete yet.
- const TagType *TagT = Context.getTypeDeclType(Tag)->getAs<TagType>();
- if (TagT && TagT->isBeingDefined())
+ QualType type = Context.getTypeDeclType(tag);
+ const TagType *tagType = type->getAs<TagType>();
+ if (tagType && tagType->isBeingDefined())
return false;
+ SourceLocation loc = SS.getLastQualifierNameLoc();
+ if (loc.isInvalid()) loc = SS.getRange().getBegin();
+
// The type must be complete.
- if (RequireCompleteType(SS.getRange().getBegin(),
- Context.getTypeDeclType(Tag),
+ if (RequireCompleteType(loc, type,
PDiag(diag::err_incomplete_nested_name_spec)
<< SS.getRange())) {
SS.SetInvalid(SS.getRange());
return true;
}
+
+ // Fixed enum types are complete, but they aren't valid as scopes
+ // until we see a definition, so awkwardly pull out this special
+ // case.
+ if (const EnumType *enumType = dyn_cast_or_null<EnumType>(tagType)) {
+ if (!enumType->getDecl()->isDefinition()) {
+ Diag(loc, diag::err_incomplete_nested_name_spec)
+ << type << SS.getRange();
+ SS.SetInvalid(SS.getRange());
+ return true;
+ }
+ }
}
return false;
Modified: cfe/trunk/test/SemaCXX/enum-scoped.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/enum-scoped.cpp?rev=134479&r1=134478&r2=134479&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/enum-scoped.cpp (original)
+++ cfe/trunk/test/SemaCXX/enum-scoped.cpp Wed Jul 6 01:57:57 2011
@@ -120,7 +120,7 @@
}
}
-// Part of PR10264
+// Part 1 of PR10264
namespace test5 {
namespace ns {
typedef unsigned Atype;
@@ -130,3 +130,15 @@
x, y, z
};
}
+
+// Part 2 of PR10264
+namespace test6 {
+ enum A : unsigned;
+ struct A::a; // expected-error {{incomplete type 'test6::A' named in nested name specifier}}
+ enum A::b; // expected-error {{incomplete type 'test6::A' named in nested name specifier}}
+ int A::c; // expected-error {{incomplete type 'test6::A' named in nested name specifier}}
+ void A::d(); // expected-error {{incomplete type 'test6::A' named in nested name specifier}}
+ void test() {
+ (void) A::e; // expected-error {{incomplete type 'test6::A' named in nested name specifier}}
+ }
+}
More information about the cfe-commits
mailing list