diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 39 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateVariadic.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 47 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 13 |
6 files changed, 95 insertions, 21 deletions
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 85343cde2ba..5f65df2ef37 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -2585,6 +2585,7 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, Result.getAllocator().CopyString(ND->getNameAsString())); break; + case DeclarationName::CXXDeductionGuideName: case DeclarationName::CXXUsingDirective: case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 32663121f88..41d977fa9c6 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4675,6 +4675,34 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { NameInfo.setLoc(Name.StartLocation); return NameInfo; + case UnqualifiedId::IK_DeductionGuideName: { + // C++ [temp.deduct.guide]p3: + // The simple-template-id shall name a class template specialization. + // The template-name shall be the same identifier as the template-name + // of the simple-template-id. + // These together intend to imply that the template-name shall name a + // class template. + // FIXME: template<typename T> struct X {}; + // template<typename T> using Y = X<T>; + // Y(int) -> Y<int>; + // satisfies these rules but does not name a class template. + TemplateName TN = Name.TemplateName.get().get(); + auto *Template = TN.getAsTemplateDecl(); + if (!Template || !isa<ClassTemplateDecl>(Template)) { + Diag(Name.StartLocation, + diag::err_deduction_guide_name_not_class_template) + << (int)getTemplateNameKindForDiagnostics(TN) << TN; + if (Template) + Diag(Template->getLocation(), diag::note_template_decl_here); + return DeclarationNameInfo(); + } + + NameInfo.setName( + Context.DeclarationNames.getCXXDeductionGuideName(Template)); + NameInfo.setLoc(Name.StartLocation); + return NameInfo; + } + case UnqualifiedId::IK_OperatorFunctionId: NameInfo.setName(Context.DeclarationNames.getCXXOperatorName( Name.OperatorFunctionId.Operator)); @@ -7621,6 +7649,15 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, R, TInfo, isInline, isExplicit, isConstexpr, SourceLocation()); + } else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) { + SemaRef.CheckDeductionGuideDeclarator(D, R, SC); + + // We don't need to store any extra information for a deduction guide, so + // just model it as a plain FunctionDecl. + return FunctionDecl::Create(SemaRef.Context, DC, + D.getLocStart(), + NameInfo, R, TInfo, SC, isInline, + true/*HasPrototype*/, isConstexpr); } else if (DC->isRecord()) { // If the name of the function is the same as the name of the record, // then this must be an invalid constructor that has a return type. @@ -8109,7 +8146,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // The explicit specifier shall be used only in the declaration of a // constructor or conversion function within its class definition; // see 12.3.1 and 12.3.2. - if (isExplicit && !NewFD->isInvalidDecl()) { + if (isExplicit && !NewFD->isInvalidDecl() && !NewFD->isDeductionGuide()) { if (!CurContext->isRecord()) { // 'explicit' was specified outside of the class. Diag(D.getDeclSpec().getExplicitSpecLoc(), diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 671d3251a54..49cf8e15ed5 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -8033,6 +8033,15 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { return Conversion; } +/// Check the validity of a declarator that we parsed for a deduction-guide. +/// These aren't actually declarators in the grammar, so we need to check that +/// the user didn't specify any pieces that are not part of the deduction-guide +/// grammar. +void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R, + StorageClass &SC) { + // FIXME: Implement +} + //===----------------------------------------------------------------------===// // Namespace Handling //===----------------------------------------------------------------------===// @@ -8613,6 +8622,9 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, Diag(Name.getLocStart(), diag::err_using_decl_template_id) << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc); return nullptr; + + case UnqualifiedId::IK_DeductionGuideName: + llvm_unreachable("cannot parse qualified deduction guide name"); } DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name); @@ -13747,6 +13759,9 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, case UnqualifiedId::IK_ConversionFunctionId: DiagArg = 2; break; + case UnqualifiedId::IK_DeductionGuideName: + DiagArg = 3; + break; case UnqualifiedId::IK_Identifier: case UnqualifiedId::IK_ImplicitSelfParam: case UnqualifiedId::IK_LiteralOperatorId: diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 54556b505ee..4ea04ac143a 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -321,6 +321,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo, case DeclarationName::CXXOperatorName: case DeclarationName::CXXLiteralOperatorName: case DeclarationName::CXXUsingDirective: + case DeclarationName::CXXDeductionGuideName: return false; case DeclarationName::CXXConstructorName: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index a59511ca77e..250f6f99464 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2733,6 +2733,17 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, D.getDeclSpec().getAttributes().getList()); break; + case UnqualifiedId::IK_DeductionGuideName: + // Deduction guides have a trailing return type and no type in their + // decl-specifier sequence. + T = SemaRef.Context.getAutoDeductType(); + if (!D.hasTrailingReturnType()) { + SemaRef.Diag(D.getName().getLocStart(), + diag::err_deduction_guide_no_trailing_return_type); + D.setInvalidType(true); + } + break; + case UnqualifiedId::IK_ConversionFunctionId: // The result type of a conversion function is the type that it // converts to. @@ -2884,20 +2895,10 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // better diagnostics. // We don't support '__auto_type' with trailing return types. // FIXME: Should we only do this for 'auto' and not 'decltype(auto)'? - if (SemaRef.getLangOpts().CPlusPlus11 && IsCXXAutoType) { - for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { - unsigned chunkIndex = e - i - 1; - state.setCurrentChunkIndex(chunkIndex); - DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex); - if (DeclType.Kind == DeclaratorChunk::Function) { - const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; - if (FTI.hasTrailingReturnType()) { - HaveTrailing = true; - Error = -1; - break; - } - } - } + if (SemaRef.getLangOpts().CPlusPlus11 && IsCXXAutoType && + D.hasTrailingReturnType()) { + HaveTrailing = true; + Error = -1; } SourceRange AutoRange = D.getDeclSpec().getTypeSpecTypeLoc(); @@ -4176,16 +4177,22 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } else if (FTI.hasTrailingReturnType()) { // T must be exactly 'auto' at this point. See CWG issue 681. if (isa<ParenType>(T)) { - S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), + S.Diag(D.getLocStart(), diag::err_trailing_return_in_parens) - << T << D.getDeclSpec().getSourceRange(); + << T << D.getSourceRange(); D.setInvalidType(true); } else if (D.getContext() != Declarator::LambdaExprContext && (T.hasQualifiers() || !isa<AutoType>(T) || - cast<AutoType>(T)->getKeyword() != AutoTypeKeyword::Auto)) { - S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), - diag::err_trailing_return_without_auto) - << T << D.getDeclSpec().getSourceRange(); + cast<AutoType>(T)->getKeyword() != + AutoTypeKeyword::Auto)) { + if (D.getName().getKind() == UnqualifiedId::IK_DeductionGuideName) + S.Diag(D.getDeclSpec().getLocStart(), + diag::err_deduction_guide_with_complex_decl) + << D.getSourceRange(); + else + S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), + diag::err_trailing_return_without_auto) + << T << D.getDeclSpec().getSourceRange(); D.setInvalidType(true); } T = S.GetTypeFromParser(FTI.getTrailingReturnType(), &TInfo); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 7019f15849a..ef349c395f8 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3617,6 +3617,19 @@ TreeTransform<Derived> case DeclarationName::CXXUsingDirective: return NameInfo; + case DeclarationName::CXXDeductionGuideName: { + TemplateDecl *OldTemplate = Name.getCXXDeductionGuideTemplate(); + TemplateDecl *NewTemplate = cast_or_null<TemplateDecl>( + getDerived().TransformDecl(NameInfo.getLoc(), OldTemplate)); + if (!NewTemplate) + return DeclarationNameInfo(); + + DeclarationNameInfo NewNameInfo(NameInfo); + NewNameInfo.setName( + SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(NewTemplate)); + return NewNameInfo; + } + case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: { |