diff options
-rw-r--r-- | clang/lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 13 | ||||
-rw-r--r-- | clang/test/SemaCXX/qualified-names-diag.cpp | 5 | ||||
-rw-r--r-- | clang/test/SemaTemplate/qualified-names-diag.cpp | 16 |
6 files changed, 47 insertions, 12 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 5106a54f952..3755744126d 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -295,6 +295,8 @@ public: SourceRange Range2 = SourceRange(), QualType PrintType = QualType()); + QualType getQualifiedNameType(const CXXScopeSpec &SS, QualType T); + //===--------------------------------------------------------------------===// // Symbol table / Decl tracking callbacks: SemaDecl.cpp. // diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 63d446f70c0..483b79a0984 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -87,13 +87,8 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, } else return 0; - if (SS && SS->isNotEmpty() && SS->isSet()) { - llvm::SmallVector<NestedNameSpecifier, 4> TNNs; - for (CXXScopeSpec::iterator TNN = SS->begin(), TNNEnd = SS->end(); - TNN != TNNEnd; ++TNN) - TNNs.push_back(NestedNameSpecifier::getFromOpaquePtr(*TNN)); - T = Context.getQualifiedNameType(&TNNs[0], TNNs.size(), T); - } + if (SS) + T = getQualifiedNameType(*SS, T); return T.getAsOpaquePtr(); } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index f5317787bac..b4e505e7c2f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -765,6 +765,9 @@ Sema::ActOnClassTemplateId(DeclTy *TemplateD, SourceLocation TemplateLoc, &TemplateArgs[0], TemplateArgs.size(), RAngleLoc); + + if (SS) + Result = getQualifiedNameType(*SS, Result); TemplateArgsIn.release(); return Result.getAsOpaquePtr(); @@ -1910,11 +1913,12 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // actually wrote the specialization, rather than formatting the // name based on the "canonical" representation used to store the // template arguments in the specialization. - Specialization->setTypeAsWritten( - Context.getClassTemplateSpecializationType(ClassTemplate, - &TemplateArgs[0], - TemplateArgs.size(), - Context.getTypeDeclType(Specialization))); + QualType WrittenTy + = Context.getClassTemplateSpecializationType(ClassTemplate, + &TemplateArgs[0], + TemplateArgs.size(), + Context.getTypeDeclType(Specialization)); + Specialization->setTypeAsWritten(getQualifiedNameType(SS, WrittenTy)); TemplateArgsIn.release(); // C++ [temp.expl.spec]p9: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index a8be924fc88..24b32e8147c 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1077,3 +1077,16 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, unsigned diag, return true; } + +/// \brief Retrieve a version of the type 'T' that is qualified by the +/// nested-name-specifier contained in SS. +QualType Sema::getQualifiedNameType(const CXXScopeSpec &SS, QualType T) { + if (!SS.isSet() || SS.isInvalid() || T.isNull()) + return T; + + llvm::SmallVector<NestedNameSpecifier, 4> Specs; + for (CXXScopeSpec::iterator Spec = SS.begin(), SpecEnd = SS.end(); + Spec != SpecEnd; ++Spec) + Specs.push_back(NestedNameSpecifier::getFromOpaquePtr(*Spec)); + return Context.getQualifiedNameType(&Specs[0], Specs.size(), T); +} diff --git a/clang/test/SemaCXX/qualified-names-diag.cpp b/clang/test/SemaCXX/qualified-names-diag.cpp index 151b924a3af..c3bd47f9e5c 100644 --- a/clang/test/SemaCXX/qualified-names-diag.cpp +++ b/clang/test/SemaCXX/qualified-names-diag.cpp @@ -15,6 +15,8 @@ namespace foo { namespace bar { typedef int y; + + struct incomplete; // expected-note{{forward declaration of 'struct incomplete'}} } void test() { foo::wibble::x a; @@ -23,6 +25,9 @@ void test() { ::foo::wibble::bar::wonka::x::y c; c + b; // expected-error{{invalid operands to binary expression ('::foo::wibble::bar::wonka::x::y' (aka 'struct y') and '::bar::y' (aka 'int'))}} + + (void)sizeof(bar::incomplete); // expected-error{{invalid application of 'sizeof' to an incomplete type 'bar::incomplete' (aka 'struct incomplete')}} } int ::foo::wibble::bar::wonka::x::y::* ptrmem; + diff --git a/clang/test/SemaTemplate/qualified-names-diag.cpp b/clang/test/SemaTemplate/qualified-names-diag.cpp new file mode 100644 index 00000000000..02bdf16b2ba --- /dev/null +++ b/clang/test/SemaTemplate/qualified-names-diag.cpp @@ -0,0 +1,16 @@ +// RUN: clang -fsyntax-only -verify %s + +namespace std { + template<typename T> class vector { }; +} + +typedef int INT; +typedef float Real; + +void test() { + using namespace std; + + std::vector<INT> v1; + vector<Real> v2; + v1 = v2; // expected-error{{incompatible type assigning 'vector<Real>' (aka 'class vector<float>'), expected 'std::vector<INT>' (aka 'class vector<int>')}} +} |