summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaCodeComplete.cpp1
-rw-r--r--clang/lib/Sema/SemaDecl.cpp39
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp15
-rw-r--r--clang/lib/Sema/SemaTemplateVariadic.cpp1
-rw-r--r--clang/lib/Sema/SemaType.cpp47
-rw-r--r--clang/lib/Sema/TreeTransform.h13
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: {
OpenPOWER on IntegriCloud