diff options
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 84 |
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)) |

