summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp84
1 files changed, 56 insertions, 28 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index c9cf86f43c4..3ed6ede53cf 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -60,6 +60,11 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) {
return DeclGroupPtrTy::make(DeclGroupRef(Ptr));
}
+static bool isTypeTemplate(NamedDecl *ND) {
+ return isa<ClassTemplateDecl>(ND) || isa<TypeAliasTemplateDecl>(ND) ||
+ isa<TemplateTemplateParmDecl>(ND);
+}
+
namespace {
class TypeNameValidatorCCC : public CorrectionCandidateCallback {
@@ -67,7 +72,7 @@ class TypeNameValidatorCCC : public CorrectionCandidateCallback {
TypeNameValidatorCCC(bool AllowInvalid, bool WantClass=false,
bool AllowTemplates=false)
: AllowInvalidDecl(AllowInvalid), WantClassName(WantClass),
- AllowClassTemplates(AllowTemplates) {
+ AllowTemplates(AllowTemplates) {
WantExpressionKeywords = false;
WantCXXNamedCasts = false;
WantRemainingKeywords = false;
@@ -76,7 +81,7 @@ class TypeNameValidatorCCC : public CorrectionCandidateCallback {
bool ValidateCandidate(const TypoCorrection &candidate) override {
if (NamedDecl *ND = candidate.getCorrectionDecl()) {
bool IsType = isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
- bool AllowedTemplate = AllowClassTemplates && isa<ClassTemplateDecl>(ND);
+ bool AllowedTemplate = AllowTemplates && isTypeTemplate(ND);
return (IsType || AllowedTemplate) &&
(AllowInvalidDecl || !ND->isInvalidDecl());
}
@@ -86,7 +91,7 @@ class TypeNameValidatorCCC : public CorrectionCandidateCallback {
private:
bool AllowInvalidDecl;
bool WantClassName;
- bool AllowClassTemplates;
+ bool AllowTemplates;
};
} // end anonymous namespace
@@ -252,7 +257,13 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
ParsedType ObjectTypePtr,
bool IsCtorOrDtorName,
bool WantNontrivialTypeSourceInfo,
+ bool IsClassTemplateDeductionContext,
IdentifierInfo **CorrectedII) {
+ // FIXME: Consider allowing this outside C++1z mode as an extension.
+ bool AllowDeducedTemplate = IsClassTemplateDeductionContext &&
+ getLangOpts().CPlusPlus1z && !IsCtorOrDtorName &&
+ !isClassName && !HasTrailingDot;
+
// Determine where we will perform name lookup.
DeclContext *LookupCtx = nullptr;
if (ObjectTypePtr) {
@@ -334,10 +345,11 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
if (CorrectedII) {
- TypoCorrection Correction = CorrectTypo(
- Result.getLookupNameInfo(), Kind, S, SS,
- llvm::make_unique<TypeNameValidatorCCC>(true, isClassName),
- CTK_ErrorRecovery);
+ TypoCorrection Correction =
+ CorrectTypo(Result.getLookupNameInfo(), Kind, S, SS,
+ llvm::make_unique<TypeNameValidatorCCC>(
+ true, isClassName, AllowDeducedTemplate),
+ CTK_ErrorRecovery);
IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo();
TemplateTy Template;
bool MemberOfUnknownSpecialization;
@@ -359,7 +371,8 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
ParsedType Ty = getTypeName(*NewII, NameLoc, S, NewSSPtr,
isClassName, HasTrailingDot, ObjectTypePtr,
IsCtorOrDtorName,
- WantNontrivialTypeSourceInfo);
+ WantNontrivialTypeSourceInfo,
+ IsClassTemplateDeductionContext);
if (Ty) {
diagnoseTypo(Correction,
PDiag(diag::err_unknown_type_or_class_name_suggest)
@@ -391,7 +404,8 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
// Look to see if we have a type anywhere in the list of results.
for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end();
Res != ResEnd; ++Res) {
- if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res)) {
+ if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res) ||
+ (AllowDeducedTemplate && isTypeTemplate(*Res))) {
if (!IIDecl ||
(*Res)->getLocation().getRawEncoding() <
IIDecl->getLocation().getRawEncoding())
@@ -440,29 +454,13 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
T = Context.getTypeDeclType(TD);
MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
-
- // NOTE: avoid constructing an ElaboratedType(Loc) if this is a
- // constructor or destructor name (in such a case, the scope specifier
- // will be attached to the enclosing Expr or Decl node).
- if (SS && SS->isNotEmpty() && !IsCtorOrDtorName) {
- if (WantNontrivialTypeSourceInfo) {
- // Construct a type with type-source information.
- TypeLocBuilder Builder;
- Builder.pushTypeSpec(T).setNameLoc(NameLoc);
-
- T = getElaboratedType(ETK_None, *SS, T);
- ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T);
- ElabTL.setElaboratedKeywordLoc(SourceLocation());
- ElabTL.setQualifierLoc(SS->getWithLocInContext(Context));
- return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
- } else {
- T = getElaboratedType(ETK_None, *SS, T);
- }
- }
} else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
(void)DiagnoseUseOfDecl(IDecl, NameLoc);
if (!HasTrailingDot)
T = Context.getObjCInterfaceType(IDecl);
+ } else if (AllowDeducedTemplate && isTypeTemplate(IIDecl)) {
+ T = Context.getDeducedTemplateSpecializationType(
+ TemplateName(cast<TemplateDecl>(IIDecl)), QualType(), false);
}
if (T.isNull()) {
@@ -470,6 +468,27 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
Result.suppressDiagnostics();
return nullptr;
}
+
+ // NOTE: avoid constructing an ElaboratedType(Loc) if this is a
+ // constructor or destructor name (in such a case, the scope specifier
+ // will be attached to the enclosing Expr or Decl node).
+ if (SS && SS->isNotEmpty() && !IsCtorOrDtorName &&
+ !isa<ObjCInterfaceDecl>(IIDecl)) {
+ if (WantNontrivialTypeSourceInfo) {
+ // Construct a type with type-source information.
+ TypeLocBuilder Builder;
+ Builder.pushTypeSpec(T).setNameLoc(NameLoc);
+
+ T = getElaboratedType(ETK_None, *SS, T);
+ ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T);
+ ElabTL.setElaboratedKeywordLoc(SourceLocation());
+ ElabTL.setQualifierLoc(SS->getWithLocInContext(Context));
+ return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
+ } else {
+ T = getElaboratedType(ETK_None, *SS, T);
+ }
+ }
+
return ParsedType::make(T);
}
@@ -647,6 +666,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
if (Corrected.getCorrectionSpecifier())
tmpSS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(),
SourceRange(IILoc));
+ // FIXME: Support class template argument deduction here.
SuggestedType =
getTypeName(*Corrected.getCorrectionAsIdentifierInfo(), IILoc, S,
tmpSS.isSet() ? &tmpSS : SS, false, false, nullptr,
@@ -9740,6 +9760,14 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
VarDeclOrName VN{VDecl, Name};
+ DeducedType *Deduced = Type->getContainedDeducedType();
+ assert(Deduced && "deduceVarTypeFromInitializer for non-deduced type");
+
+ if (isa<DeducedTemplateSpecializationType>(Deduced)) {
+ Diag(Init->getLocStart(), diag::err_deduced_class_template_not_supported);
+ return QualType();
+ }
+
ArrayRef<Expr *> DeduceInits = Init;
if (DirectInit) {
if (auto *PL = dyn_cast<ParenListExpr>(Init))
OpenPOWER on IntegriCloud