aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-09-11 04:59:25 +0000
committerJohn McCall <rjmccall@apple.com>2009-09-11 04:59:25 +0000
commitc4e7019d5c9034a2d84ee4695f8e98dc025ac131 (patch)
treeda8b19b3e6e6f62ddc50db7209b8dd0421fd15a8 /lib/Sema
parent66847a2826c97b8e09aec304a0a7b4fe1dc35969 (diff)
Support elaborated dependent types and diagnose tag mismatches.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81504 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.h10
-rw-r--r--lib/Sema/SemaDecl.cpp12
-rw-r--r--lib/Sema/SemaTemplate.cpp31
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp32
4 files changed, 80 insertions, 5 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index dc41aba094..b17e54ebe3 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -609,7 +609,15 @@ public:
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr, AccessSpecifier AS,
MultiTemplateParamsArg TemplateParameterLists,
- bool &OwnedDecl);
+ bool &OwnedDecl, bool &IsDependent);
+
+ virtual TypeResult ActOnDependentTag(Scope *S,
+ unsigned TagSpec,
+ TagUseKind TUK,
+ const CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation TagLoc,
+ SourceLocation NameLoc);
virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart,
IdentifierInfo *ClassName,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 65516f2c29..53fab18017 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3988,7 +3988,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr, AccessSpecifier AS,
MultiTemplateParamsArg TemplateParameterLists,
- bool &OwnedDecl) {
+ bool &OwnedDecl, bool &IsDependent) {
// If this is not a definition, it must have a name.
assert((Name != 0 || TUK == TUK_Definition) &&
"Nameless record must be a definition!");
@@ -4034,6 +4034,16 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
goto CreateNewDecl;
}
+ // If this is a friend or a reference to a class in a dependent
+ // context, don't try to make a decl for it.
+ if (TUK == TUK_Friend || TUK == TUK_Reference) {
+ DC = computeDeclContext(SS, false);
+ if (!DC) {
+ IsDependent = true;
+ return DeclPtrTy();
+ }
+ }
+
if (RequireCompleteDeclContext(SS))
return DeclPtrTy::make((Decl *)0);
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index fceac854ee..63c29de82b 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1159,9 +1159,10 @@ Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult,
if (!isAcceptableTagRedeclaration(D, TagKind, TagLoc, *Id)) {
Diag(TagLoc, diag::err_use_with_wrong_tag)
- << Id
+ << Type
<< CodeModificationHint::CreateReplacement(SourceRange(TagLoc),
D->getKindName());
+ Diag(D->getLocation(), diag::note_previous_use);
}
}
@@ -3058,9 +3059,13 @@ Sema::ActOnExplicitInstantiation(Scope *S,
AttributeList *Attr) {
bool Owned = false;
+ bool IsDependent = false;
DeclPtrTy TagD = ActOnTag(S, TagSpec, Action::TUK_Reference,
KWLoc, SS, Name, NameLoc, Attr, AS_none,
- MultiTemplateParamsArg(*this, 0, 0), Owned);
+ MultiTemplateParamsArg(*this, 0, 0),
+ Owned, IsDependent);
+ assert(!IsDependent && "explicit instantiation of dependent name not yet handled");
+
if (!TagD)
return true;
@@ -3124,6 +3129,28 @@ Sema::ActOnExplicitInstantiation(Scope *S,
}
Sema::TypeResult
+Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+ const CXXScopeSpec &SS, IdentifierInfo *Name,
+ SourceLocation TagLoc, SourceLocation NameLoc) {
+ // This has to hold, because SS is expected to be defined.
+ assert(Name && "Expected a name in a dependent tag");
+
+ NestedNameSpecifier *NNS
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ if (!NNS)
+ return true;
+
+ QualType T = CheckTypenameType(NNS, *Name, SourceRange(TagLoc, NameLoc));
+ if (T.isNull())
+ return true;
+
+ TagDecl::TagKind TagKind = TagDecl::getTagKindForTypeSpec(TagSpec);
+ QualType ElabType = Context.getElaboratedType(T, TagKind);
+
+ return ElabType.getAsOpaquePtr();
+}
+
+Sema::TypeResult
Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
const IdentifierInfo &II, SourceLocation IdLoc) {
NestedNameSpecifier *NNS
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 651d4a50dc..e719bbde92 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -391,6 +391,10 @@ namespace {
IdentifierInfo *Name,
SourceLocation Loc, SourceRange TypeRange);
+ /// \brief Check for tag mismatches when instantiating an
+ /// elaborated type.
+ QualType RebuildElaboratedType(QualType T, ElaboratedType::TagKind Tag);
+
Sema::OwningExprResult TransformPredefinedExpr(PredefinedExpr *E);
Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E);
@@ -451,7 +455,33 @@ TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl,
return Var;
}
-Sema::OwningExprResult
+QualType
+TemplateInstantiator::RebuildElaboratedType(QualType T,
+ ElaboratedType::TagKind Tag) {
+ if (const TagType *TT = T->getAs<TagType>()) {
+ TagDecl* TD = TT->getDecl();
+
+ // FIXME: this location is very wrong; we really need typelocs.
+ SourceLocation TagLocation = TD->getTagKeywordLoc();
+
+ // FIXME: type might be anonymous.
+ IdentifierInfo *Id = TD->getIdentifier();
+
+ // TODO: should we even warn on struct/class mismatches for this? Seems
+ // like it's likely to produce a lot of spurious errors.
+ if (!SemaRef.isAcceptableTagRedeclaration(TD, Tag, TagLocation, *Id)) {
+ SemaRef.Diag(TagLocation, diag::err_use_with_wrong_tag)
+ << Id
+ << CodeModificationHint::CreateReplacement(SourceRange(TagLocation),
+ TD->getKindName());
+ SemaRef.Diag(TD->getLocation(), diag::note_previous_use);
+ }
+ }
+
+ return TreeTransform<TemplateInstantiator>::RebuildElaboratedType(T, Tag);
+}
+
+Sema::OwningExprResult
TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
if (!E->isTypeDependent())
return SemaRef.Owned(E->Retain());