aboutsummaryrefslogtreecommitdiff
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.cpp800
1 files changed, 439 insertions, 361 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 205f58000302..4fcc01012d44 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -141,6 +141,7 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
case tok::kw___bf16:
case tok::kw__Float16:
case tok::kw___float128:
+ case tok::kw___ibm128:
case tok::kw_wchar_t:
case tok::kw_bool:
case tok::kw___underlying_type:
@@ -1920,8 +1921,10 @@ void Sema::DiagnoseUnusedDecl(const NamedDecl *D) {
}
void Sema::DiagnoseUnusedButSetDecl(const VarDecl *VD) {
- // If it's not referenced, it can't be set.
- if (!VD->isReferenced() || !VD->getDeclName() || VD->hasAttr<UnusedAttr>())
+ // If it's not referenced, it can't be set. If it has the Cleanup attribute,
+ // it's not really unused.
+ if (!VD->isReferenced() || !VD->getDeclName() || VD->hasAttr<UnusedAttr>() ||
+ VD->hasAttr<CleanupAttr>())
return;
const auto *Ty = VD->getType().getTypePtr()->getBaseElementTypeUnsafe();
@@ -1941,6 +1944,12 @@ void Sema::DiagnoseUnusedButSetDecl(const VarDecl *VD) {
}
}
+ // Don't warn about __block Objective-C pointer variables, as they might
+ // be assigned in the block but not used elsewhere for the purpose of lifetime
+ // extension.
+ if (VD->hasAttr<BlocksAttr>() && Ty->isObjCObjectPointerType())
+ return;
+
auto iter = RefsMinusAssignments.find(VD);
if (iter == RefsMinusAssignments.end())
return;
@@ -2113,8 +2122,9 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, QualType Type,
}
FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type,
- /*TInfo=*/nullptr, SC_Extern, false,
- Type->isFunctionProtoType());
+ /*TInfo=*/nullptr, SC_Extern,
+ getCurFPFeatures().isFPConstrained(),
+ false, Type->isFunctionProtoType());
New->setImplicit();
New->addAttr(BuiltinAttr::CreateImplicit(Context, ID));
@@ -2627,6 +2637,8 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
NewAttr = S.mergeDLLImportAttr(D, *ImportA);
else if (const auto *ExportA = dyn_cast<DLLExportAttr>(Attr))
NewAttr = S.mergeDLLExportAttr(D, *ExportA);
+ else if (const auto *EA = dyn_cast<ErrorAttr>(Attr))
+ NewAttr = S.mergeErrorAttr(D, *EA, EA->getUserDiagnostic());
else if (const auto *FA = dyn_cast<FormatAttr>(Attr))
NewAttr = S.mergeFormatAttr(D, *FA, FA->getType(), FA->getFormatIdx(),
FA->getFirstArg());
@@ -2673,6 +2685,8 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
NewAttr = S.mergeEnforceTCBAttr(D, *TCBA);
else if (const auto *TCBLA = dyn_cast<EnforceTCBLeafAttr>(Attr))
NewAttr = S.mergeEnforceTCBLeafAttr(D, *TCBLA);
+ else if (const auto *BTFA = dyn_cast<BTFDeclTagAttr>(Attr))
+ NewAttr = S.mergeBTFDeclTagAttr(D, *BTFA);
else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr))
NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
@@ -2954,8 +2968,7 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
if (const auto *NewAbiTagAttr = New->getAttr<AbiTagAttr>()) {
if (const auto *OldAbiTagAttr = Old->getAttr<AbiTagAttr>()) {
for (const auto &NewTag : NewAbiTagAttr->tags()) {
- if (std::find(OldAbiTagAttr->tags_begin(), OldAbiTagAttr->tags_end(),
- NewTag) == OldAbiTagAttr->tags_end()) {
+ if (!llvm::is_contained(OldAbiTagAttr->tags(), NewTag)) {
Diag(NewAbiTagAttr->getLocation(),
diag::err_new_abi_tag_on_redeclaration)
<< NewTag;
@@ -3352,12 +3365,20 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
}
}
- if (New->hasAttr<InternalLinkageAttr>() &&
- !Old->hasAttr<InternalLinkageAttr>()) {
- Diag(New->getLocation(), diag::err_internal_linkage_redeclaration)
- << New->getDeclName();
- notePreviousDefinition(Old, New->getLocation());
- New->dropAttr<InternalLinkageAttr>();
+ if (const auto *ILA = New->getAttr<InternalLinkageAttr>())
+ if (!Old->hasAttr<InternalLinkageAttr>()) {
+ Diag(New->getLocation(), diag::err_attribute_missing_on_first_decl)
+ << ILA;
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ New->dropAttr<InternalLinkageAttr>();
+ }
+
+ if (auto *EA = New->getAttr<ErrorAttr>()) {
+ if (!Old->hasAttr<ErrorAttr>()) {
+ Diag(EA->getLocation(), diag::err_attribute_missing_on_first_decl) << EA;
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ New->dropAttr<ErrorAttr>();
+ }
}
if (CheckRedeclarationModuleOwnership(New, Old))
@@ -3592,14 +3613,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
// defined, copy the deduced value from the old declaration.
AutoType *OldAT = Old->getReturnType()->getContainedAutoType();
if (OldAT && OldAT->isDeduced()) {
- New->setType(
- SubstAutoType(New->getType(),
- OldAT->isDependentType() ? Context.DependentTy
- : OldAT->getDeducedType()));
- NewQType = Context.getCanonicalType(
- SubstAutoType(NewQType,
- OldAT->isDependentType() ? Context.DependentTy
- : OldAT->getDeducedType()));
+ QualType DT = OldAT->getDeducedType();
+ if (DT.isNull()) {
+ New->setType(SubstAutoTypeDependent(New->getType()));
+ NewQType = Context.getCanonicalType(SubstAutoTypeDependent(NewQType));
+ } else {
+ New->setType(SubstAutoType(New->getType(), DT));
+ NewQType = Context.getCanonicalType(SubstAutoType(NewQType, DT));
+ }
}
}
@@ -3677,12 +3698,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
// The first declaration of a function shall specify the noreturn
// attribute if any declaration of that function specifies the noreturn
// attribute.
- const CXX11NoReturnAttr *NRA = New->getAttr<CXX11NoReturnAttr>();
- if (NRA && !Old->hasAttr<CXX11NoReturnAttr>()) {
- Diag(NRA->getLocation(), diag::err_noreturn_missing_on_first_decl);
- Diag(Old->getFirstDecl()->getLocation(),
- diag::note_noreturn_missing_first_decl);
- }
+ if (const auto *NRA = New->getAttr<CXX11NoReturnAttr>())
+ if (!Old->hasAttr<CXX11NoReturnAttr>()) {
+ Diag(NRA->getLocation(), diag::err_attribute_missing_on_first_decl)
+ << NRA;
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ }
// C++11 [dcl.attr.depend]p2:
// The first declaration of a function shall specify the
@@ -4160,18 +4181,18 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
Old->getStorageClass() == SC_None &&
!Old->hasAttr<WeakImportAttr>()) {
Diag(New->getLocation(), diag::warn_weak_import) << New->getDeclName();
- notePreviousDefinition(Old, New->getLocation());
+ Diag(Old->getLocation(), diag::note_previous_declaration);
// Remove weak_import attribute on new declaration.
New->dropAttr<WeakImportAttr>();
}
- if (New->hasAttr<InternalLinkageAttr>() &&
- !Old->hasAttr<InternalLinkageAttr>()) {
- Diag(New->getLocation(), diag::err_internal_linkage_redeclaration)
- << New->getDeclName();
- notePreviousDefinition(Old, New->getLocation());
- New->dropAttr<InternalLinkageAttr>();
- }
+ if (const auto *ILA = New->getAttr<InternalLinkageAttr>())
+ if (!Old->hasAttr<InternalLinkageAttr>()) {
+ Diag(New->getLocation(), diag::err_attribute_missing_on_first_decl)
+ << ILA;
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ New->dropAttr<InternalLinkageAttr>();
+ }
// Merge the types.
VarDecl *MostRecent = Old->getMostRecentDecl();
@@ -5281,8 +5302,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// trivial in almost all cases, except if a union member has an in-class
// initializer:
// union { int n = 0; };
- if (!Invalid)
- ActOnUninitializedDecl(Anon);
+ ActOnUninitializedDecl(Anon);
}
Anon->setImplicit();
@@ -5761,8 +5781,8 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data());
while (SpecLoc.getPrefix())
SpecLoc = SpecLoc.getPrefix();
- if (dyn_cast_or_null<DecltypeType>(
- SpecLoc.getNestedNameSpecifier()->getAsType()))
+ if (isa_and_nonnull<DecltypeType>(
+ SpecLoc.getNestedNameSpecifier()->getAsType()))
Diag(Loc, diag::err_decltype_in_declarator)
<< SpecLoc.getTypeLoc().getSourceRange();
@@ -7327,10 +7347,9 @@ NamedDecl *Sema::ActOnVariableDeclarator(
DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec();
if (TSC != TSCS_unspecified) {
- bool IsCXX = getLangOpts().OpenCLCPlusPlus;
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_opencl_unknown_type_specifier)
- << IsCXX << getLangOpts().getOpenCLVersionTuple().getAsString()
+ << getLangOpts().getOpenCLVersionString()
<< DeclSpec::getSpecifierName(TSC) << 1;
NewVD->setInvalidDecl();
}
@@ -8552,10 +8571,11 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
(D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) ||
(!R->getAsAdjusted<FunctionType>() && R->isFunctionProtoType());
- NewFD = FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo,
- R, TInfo, SC, isInline, HasPrototype,
- ConstexprSpecKind::Unspecified,
- /*TrailingRequiresClause=*/nullptr);
+ NewFD = FunctionDecl::Create(
+ SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC,
+ SemaRef.getCurFPFeatures().isFPConstrained(), isInline, HasPrototype,
+ ConstexprSpecKind::Unspecified,
+ /*TrailingRequiresClause=*/nullptr);
if (D.isInvalidType())
NewFD->setInvalidDecl();
@@ -8591,9 +8611,9 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
R = SemaRef.CheckConstructorDeclarator(D, R, SC);
return CXXConstructorDecl::Create(
SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
- TInfo, ExplicitSpecifier, isInline,
- /*isImplicitlyDeclared=*/false, ConstexprKind, InheritedConstructor(),
- TrailingRequiresClause);
+ TInfo, ExplicitSpecifier, SemaRef.getCurFPFeatures().isFPConstrained(),
+ isInline, /*isImplicitlyDeclared=*/false, ConstexprKind,
+ InheritedConstructor(), TrailingRequiresClause);
} else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
// This is a C++ destructor declaration.
@@ -8602,7 +8622,8 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
CXXDestructorDecl *NewDD = CXXDestructorDecl::Create(
SemaRef.Context, Record, D.getBeginLoc(), NameInfo, R, TInfo,
- isInline, /*isImplicitlyDeclared=*/false, ConstexprKind,
+ SemaRef.getCurFPFeatures().isFPConstrained(), isInline,
+ /*isImplicitlyDeclared=*/false, ConstexprKind,
TrailingRequiresClause);
// If the destructor needs an implicit exception specification, set it
@@ -8620,11 +8641,10 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
// Create a FunctionDecl to satisfy the function definition parsing
// code path.
- return FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(),
- D.getIdentifierLoc(), Name, R, TInfo, SC,
- isInline,
- /*hasPrototype=*/true, ConstexprKind,
- TrailingRequiresClause);
+ return FunctionDecl::Create(
+ SemaRef.Context, DC, D.getBeginLoc(), D.getIdentifierLoc(), Name, R,
+ TInfo, SC, SemaRef.getCurFPFeatures().isFPConstrained(), isInline,
+ /*hasPrototype=*/true, ConstexprKind, TrailingRequiresClause);
}
} else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
@@ -8641,7 +8661,8 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
IsVirtualOkay = true;
return CXXConversionDecl::Create(
SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
- TInfo, isInline, ExplicitSpecifier, ConstexprKind, SourceLocation(),
+ TInfo, SemaRef.getCurFPFeatures().isFPConstrained(), isInline,
+ ExplicitSpecifier, ConstexprKind, SourceLocation(),
TrailingRequiresClause);
} else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
@@ -8670,8 +8691,8 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
// This is a C++ method declaration.
CXXMethodDecl *Ret = CXXMethodDecl::Create(
SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
- TInfo, SC, isInline, ConstexprKind, SourceLocation(),
- TrailingRequiresClause);
+ TInfo, SC, SemaRef.getCurFPFeatures().isFPConstrained(), isInline,
+ ConstexprKind, SourceLocation(), TrailingRequiresClause);
IsVirtualOkay = !Ret->isStatic();
return Ret;
} else {
@@ -8683,9 +8704,10 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
// Determine whether the function was written with a
// prototype. This true when:
// - we're in C++ (where every function has a prototype),
- return FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo,
- R, TInfo, SC, isInline, true /*HasPrototype*/,
- ConstexprKind, TrailingRequiresClause);
+ return FunctionDecl::Create(
+ SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC,
+ SemaRef.getCurFPFeatures().isFPConstrained(), isInline,
+ true /*HasPrototype*/, ConstexprKind, TrailingRequiresClause);
}
}
@@ -8819,8 +8841,7 @@ static void checkIsValidOpenCLKernelParameter(
// OpenCL v3.0 s6.11.a:
// A kernel function argument cannot be declared as a pointer to a pointer
// type. [...] This restriction only applies to OpenCL C 1.2 or below.
- if (S.getLangOpts().OpenCLVersion <= 120 &&
- !S.getLangOpts().OpenCLCPlusPlus) {
+ if (S.getLangOpts().getOpenCLCompatibleVersion() <= 120) {
S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param);
D.setInvalidType();
return;
@@ -9087,8 +9108,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// C++ [class.union]p2
// A union can have member functions, but not virtual functions.
- if (isVirtual && Parent->isUnion())
+ if (isVirtual && Parent->isUnion()) {
Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_in_union);
+ NewFD->setInvalidDecl();
+ }
}
SetNestedNameSpecifier(*this, NewFD, D);
@@ -9235,8 +9258,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// a friend yet, so 'isDependentContext' on the FD doesn't work.
const FunctionProtoType *FPT =
NewFD->getType()->castAs<FunctionProtoType>();
- QualType Result =
- SubstAutoType(FPT->getReturnType(), Context.DependentTy);
+ QualType Result = SubstAutoTypeDependent(FPT->getReturnType());
NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(),
FPT->getExtProtoInfo()));
}
@@ -9554,9 +9576,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
- if (LangOpts.SYCLIsDevice || (LangOpts.OpenMP && LangOpts.OpenMPIsDevice))
- checkDeviceDecl(NewFD, D.getBeginLoc());
-
if (!getLangOpts().CPlusPlus) {
// Perform semantic checking on the function declaration.
if (!NewFD->isInvalidDecl() && NewFD->isMain())
@@ -9955,8 +9974,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (getLangOpts().OpenCL && NewFD->hasAttr<OpenCLKernelAttr>()) {
// OpenCL v1.2 s6.8 static is invalid for kernel functions.
- if ((getLangOpts().OpenCLVersion >= 120)
- && (SC == SC_Static)) {
+ if (SC == SC_Static) {
Diag(D.getIdentifierLoc(), diag::err_static_kernel);
D.setInvalidType();
}
@@ -10002,7 +10020,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// OpenCL 2.0 pipe restrictions forbids pipe packet types to be non-value
// types.
- if (getLangOpts().OpenCLVersion >= 200 || getLangOpts().OpenCLCPlusPlus) {
+ if (getLangOpts().getOpenCLCompatibleVersion() >= 200) {
if(const PipeType *PipeTy = PT->getAs<PipeType>()) {
QualType ElemTy = PipeTy->getElementType();
if (ElemTy->isReferenceType() || ElemTy->isPointerType()) {
@@ -10306,8 +10324,8 @@ bool Sema::areMultiversionVariantFunctionsCompatible(
ReturnType = 1,
ConstexprSpec = 2,
InlineSpec = 3,
- StorageClass = 4,
- Linkage = 5,
+ Linkage = 4,
+ LanguageLinkage = 5,
};
if (NoProtoDiagID.getDiagID() != 0 && OldFD &&
@@ -10381,11 +10399,11 @@ bool Sema::areMultiversionVariantFunctionsCompatible(
if (OldFD->isInlineSpecified() != NewFD->isInlineSpecified())
return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << InlineSpec;
- if (OldFD->getStorageClass() != NewFD->getStorageClass())
- return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << StorageClass;
+ if (OldFD->getFormalLinkage() != NewFD->getFormalLinkage())
+ return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << Linkage;
if (!CLinkageMayDiffer && OldFD->isExternC() != NewFD->isExternC())
- return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << Linkage;
+ return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << LanguageLinkage;
if (CheckEquivalentExceptionSpec(
OldFD->getType()->getAs<FunctionProtoType>(), OldFD->getLocation(),
@@ -12331,7 +12349,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
/*TreatUnavailableAsInvalid=*/false);
ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT);
if (Result.isInvalid()) {
- // If the provied initializer fails to initialize the var decl,
+ // If the provided initializer fails to initialize the var decl,
// we attach a recovery expr for better recovery.
auto RecoveryExpr =
CreateRecoveryExpr(Init->getBeginLoc(), Init->getEndLoc(), Args);
@@ -12595,7 +12613,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
VDecl->setInitStyle(VarDecl::ListInit);
}
- if (LangOpts.OpenMP && VDecl->isFileVarDecl())
+ if (LangOpts.OpenMP &&
+ (LangOpts.OpenMPIsDevice || !LangOpts.OMPTargetTriples.empty()) &&
+ VDecl->isFileVarDecl())
DeclsToCheckForDeferredDiags.insert(VDecl);
CheckCompleteVariableDeclaration(VDecl);
}
@@ -14477,7 +14497,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
FunctionScopeInfo *FSI = getCurFunction();
FunctionDecl *FD = dcl ? dcl->getAsFunction() : nullptr;
- if (FSI->UsesFPIntrin && !FD->hasAttr<StrictFPAttr>())
+ if (FSI->UsesFPIntrin && FD && !FD->hasAttr<StrictFPAttr>())
FD->addAttr(StrictFPAttr::CreateImplicit(Context));
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
@@ -14486,333 +14506,340 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (getLangOpts().Coroutines && FSI->isCoroutine())
CheckCompletedCoroutineBody(FD, Body);
- // Do not call PopExpressionEvaluationContext() if it is a lambda because one
- // is already popped when finishing the lambda in BuildLambdaExpr(). This is
- // meant to pop the context added in ActOnStartOfFunctionDef().
- ExitFunctionBodyRAII ExitRAII(*this, isLambdaCallOperator(FD));
+ {
+ // Do not call PopExpressionEvaluationContext() if it is a lambda because
+ // one is already popped when finishing the lambda in BuildLambdaExpr().
+ // This is meant to pop the context added in ActOnStartOfFunctionDef().
+ ExitFunctionBodyRAII ExitRAII(*this, isLambdaCallOperator(FD));
- if (FD) {
- FD->setBody(Body);
- FD->setWillHaveBody(false);
+ if (FD) {
+ FD->setBody(Body);
+ FD->setWillHaveBody(false);
- if (getLangOpts().CPlusPlus14) {
- if (!FD->isInvalidDecl() && Body && !FD->isDependentContext() &&
- FD->getReturnType()->isUndeducedType()) {
- // If the function has a deduced result type but contains no 'return'
- // statements, the result type as written must be exactly 'auto', and
- // the deduced result type is 'void'.
- if (!FD->getReturnType()->getAs<AutoType>()) {
- Diag(dcl->getLocation(), diag::err_auto_fn_no_return_but_not_auto)
- << FD->getReturnType();
- FD->setInvalidDecl();
- } else {
- // Substitute 'void' for the 'auto' in the type.
- TypeLoc ResultType = getReturnTypeLoc(FD);
- Context.adjustDeducedFunctionResultType(
- FD, SubstAutoType(ResultType.getType(), Context.VoidTy));
+ if (getLangOpts().CPlusPlus14) {
+ if (!FD->isInvalidDecl() && Body && !FD->isDependentContext() &&
+ FD->getReturnType()->isUndeducedType()) {
+ // If the function has a deduced result type but contains no 'return'
+ // statements, the result type as written must be exactly 'auto', and
+ // the deduced result type is 'void'.
+ if (!FD->getReturnType()->getAs<AutoType>()) {
+ Diag(dcl->getLocation(), diag::err_auto_fn_no_return_but_not_auto)
+ << FD->getReturnType();
+ FD->setInvalidDecl();
+ } else {
+ // Substitute 'void' for the 'auto' in the type.
+ TypeLoc ResultType = getReturnTypeLoc(FD);
+ Context.adjustDeducedFunctionResultType(
+ FD, SubstAutoType(ResultType.getType(), Context.VoidTy));
+ }
}
- }
- } else if (getLangOpts().CPlusPlus11 && isLambdaCallOperator(FD)) {
- // In C++11, we don't use 'auto' deduction rules for lambda call
- // operators because we don't support return type deduction.
- auto *LSI = getCurLambda();
- if (LSI->HasImplicitReturnType) {
- deduceClosureReturnType(*LSI);
+ } else if (getLangOpts().CPlusPlus11 && isLambdaCallOperator(FD)) {
+ // In C++11, we don't use 'auto' deduction rules for lambda call
+ // operators because we don't support return type deduction.
+ auto *LSI = getCurLambda();
+ if (LSI->HasImplicitReturnType) {
+ deduceClosureReturnType(*LSI);
- // C++11 [expr.prim.lambda]p4:
- // [...] if there are no return statements in the compound-statement
- // [the deduced type is] the type void
- QualType RetType =
- LSI->ReturnType.isNull() ? Context.VoidTy : LSI->ReturnType;
+ // C++11 [expr.prim.lambda]p4:
+ // [...] if there are no return statements in the compound-statement
+ // [the deduced type is] the type void
+ QualType RetType =
+ LSI->ReturnType.isNull() ? Context.VoidTy : LSI->ReturnType;
- // Update the return type to the deduced type.
- const auto *Proto = FD->getType()->castAs<FunctionProtoType>();
- FD->setType(Context.getFunctionType(RetType, Proto->getParamTypes(),
- Proto->getExtProtoInfo()));
+ // Update the return type to the deduced type.
+ const auto *Proto = FD->getType()->castAs<FunctionProtoType>();
+ FD->setType(Context.getFunctionType(RetType, Proto->getParamTypes(),
+ Proto->getExtProtoInfo()));
+ }
}
- }
- // If the function implicitly returns zero (like 'main') or is naked,
- // don't complain about missing return statements.
- if (FD->hasImplicitReturnZero() || FD->hasAttr<NakedAttr>())
- WP.disableCheckFallThrough();
+ // If the function implicitly returns zero (like 'main') or is naked,
+ // don't complain about missing return statements.
+ if (FD->hasImplicitReturnZero() || FD->hasAttr<NakedAttr>())
+ WP.disableCheckFallThrough();
- // MSVC permits the use of pure specifier (=0) on function definition,
- // defined at class scope, warn about this non-standard construct.
- if (getLangOpts().MicrosoftExt && FD->isPure() && !FD->isOutOfLine())
- Diag(FD->getLocation(), diag::ext_pure_function_definition);
+ // MSVC permits the use of pure specifier (=0) on function definition,
+ // defined at class scope, warn about this non-standard construct.
+ if (getLangOpts().MicrosoftExt && FD->isPure() && !FD->isOutOfLine())
+ Diag(FD->getLocation(), diag::ext_pure_function_definition);
- if (!FD->isInvalidDecl()) {
- // Don't diagnose unused parameters of defaulted or deleted functions.
- if (!FD->isDeleted() && !FD->isDefaulted() && !FD->hasSkippedBody())
- DiagnoseUnusedParameters(FD->parameters());
- DiagnoseSizeOfParametersAndReturnValue(FD->parameters(),
- FD->getReturnType(), FD);
+ if (!FD->isInvalidDecl()) {
+ // Don't diagnose unused parameters of defaulted or deleted functions.
+ if (!FD->isDeleted() && !FD->isDefaulted() && !FD->hasSkippedBody())
+ DiagnoseUnusedParameters(FD->parameters());
+ DiagnoseSizeOfParametersAndReturnValue(FD->parameters(),
+ FD->getReturnType(), FD);
- // If this is a structor, we need a vtable.
- if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(FD))
- MarkVTableUsed(FD->getLocation(), Constructor->getParent());
- else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(FD))
- MarkVTableUsed(FD->getLocation(), Destructor->getParent());
+ // If this is a structor, we need a vtable.
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(FD))
+ MarkVTableUsed(FD->getLocation(), Constructor->getParent());
+ else if (CXXDestructorDecl *Destructor =
+ dyn_cast<CXXDestructorDecl>(FD))
+ MarkVTableUsed(FD->getLocation(), Destructor->getParent());
- // Try to apply the named return value optimization. We have to check
- // if we can do this here because lambdas keep return statements around
- // to deduce an implicit return type.
- if (FD->getReturnType()->isRecordType() &&
- (!getLangOpts().CPlusPlus || !FD->isDependentContext()))
- computeNRVO(Body, FSI);
- }
+ // Try to apply the named return value optimization. We have to check
+ // if we can do this here because lambdas keep return statements around
+ // to deduce an implicit return type.
+ if (FD->getReturnType()->isRecordType() &&
+ (!getLangOpts().CPlusPlus || !FD->isDependentContext()))
+ computeNRVO(Body, FSI);
+ }
- // GNU warning -Wmissing-prototypes:
- // Warn if a global function is defined without a previous
- // prototype declaration. This warning is issued even if the
- // definition itself provides a prototype. The aim is to detect
- // global functions that fail to be declared in header files.
- const FunctionDecl *PossiblePrototype = nullptr;
- if (ShouldWarnAboutMissingPrototype(FD, PossiblePrototype)) {
- Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
+ // GNU warning -Wmissing-prototypes:
+ // Warn if a global function is defined without a previous
+ // prototype declaration. This warning is issued even if the
+ // definition itself provides a prototype. The aim is to detect
+ // global functions that fail to be declared in header files.
+ const FunctionDecl *PossiblePrototype = nullptr;
+ if (ShouldWarnAboutMissingPrototype(FD, PossiblePrototype)) {
+ Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
- if (PossiblePrototype) {
- // We found a declaration that is not a prototype,
- // but that could be a zero-parameter prototype
- if (TypeSourceInfo *TI = PossiblePrototype->getTypeSourceInfo()) {
- TypeLoc TL = TI->getTypeLoc();
- if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>())
- Diag(PossiblePrototype->getLocation(),
- diag::note_declaration_not_a_prototype)
- << (FD->getNumParams() != 0)
- << (FD->getNumParams() == 0
- ? FixItHint::CreateInsertion(FTL.getRParenLoc(), "void")
- : FixItHint{});
- }
- } else {
- // Returns true if the token beginning at this Loc is `const`.
- auto isLocAtConst = [&](SourceLocation Loc, const SourceManager &SM,
- const LangOptions &LangOpts) {
- std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
- if (LocInfo.first.isInvalid())
- return false;
+ if (PossiblePrototype) {
+ // We found a declaration that is not a prototype,
+ // but that could be a zero-parameter prototype
+ if (TypeSourceInfo *TI = PossiblePrototype->getTypeSourceInfo()) {
+ TypeLoc TL = TI->getTypeLoc();
+ if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>())
+ Diag(PossiblePrototype->getLocation(),
+ diag::note_declaration_not_a_prototype)
+ << (FD->getNumParams() != 0)
+ << (FD->getNumParams() == 0 ? FixItHint::CreateInsertion(
+ FTL.getRParenLoc(), "void")
+ : FixItHint{});
+ }
+ } else {
+ // Returns true if the token beginning at this Loc is `const`.
+ auto isLocAtConst = [&](SourceLocation Loc, const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+ if (LocInfo.first.isInvalid())
+ return false;
- bool Invalid = false;
- StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
- if (Invalid)
- return false;
+ bool Invalid = false;
+ StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
+ if (Invalid)
+ return false;
- if (LocInfo.second > Buffer.size())
- return false;
+ if (LocInfo.second > Buffer.size())
+ return false;
- const char *LexStart = Buffer.data() + LocInfo.second;
- StringRef StartTok(LexStart, Buffer.size() - LocInfo.second);
+ const char *LexStart = Buffer.data() + LocInfo.second;
+ StringRef StartTok(LexStart, Buffer.size() - LocInfo.second);
- return StartTok.consume_front("const") &&
- (StartTok.empty() || isWhitespace(StartTok[0]) ||
- StartTok.startswith("/*") || StartTok.startswith("//"));
- };
+ return StartTok.consume_front("const") &&
+ (StartTok.empty() || isWhitespace(StartTok[0]) ||
+ StartTok.startswith("/*") || StartTok.startswith("//"));
+ };
- auto findBeginLoc = [&]() {
- // If the return type has `const` qualifier, we want to insert
- // `static` before `const` (and not before the typename).
- if ((FD->getReturnType()->isAnyPointerType() &&
- FD->getReturnType()->getPointeeType().isConstQualified()) ||
- FD->getReturnType().isConstQualified()) {
- // But only do this if we can determine where the `const` is.
+ auto findBeginLoc = [&]() {
+ // If the return type has `const` qualifier, we want to insert
+ // `static` before `const` (and not before the typename).
+ if ((FD->getReturnType()->isAnyPointerType() &&
+ FD->getReturnType()->getPointeeType().isConstQualified()) ||
+ FD->getReturnType().isConstQualified()) {
+ // But only do this if we can determine where the `const` is.
- if (isLocAtConst(FD->getBeginLoc(), getSourceManager(),
- getLangOpts()))
+ if (isLocAtConst(FD->getBeginLoc(), getSourceManager(),
+ getLangOpts()))
- return FD->getBeginLoc();
- }
- return FD->getTypeSpecStartLoc();
- };
- Diag(FD->getTypeSpecStartLoc(), diag::note_static_for_internal_linkage)
- << /* function */ 1
- << (FD->getStorageClass() == SC_None
- ? FixItHint::CreateInsertion(findBeginLoc(), "static ")
- : FixItHint{});
- }
+ return FD->getBeginLoc();
+ }
+ return FD->getTypeSpecStartLoc();
+ };
+ Diag(FD->getTypeSpecStartLoc(),
+ diag::note_static_for_internal_linkage)
+ << /* function */ 1
+ << (FD->getStorageClass() == SC_None
+ ? FixItHint::CreateInsertion(findBeginLoc(), "static ")
+ : FixItHint{});
+ }
- // GNU warning -Wstrict-prototypes
- // Warn if K&R function is defined without a previous declaration.
- // This warning is issued only if the definition itself does not provide
- // a prototype. Only K&R definitions do not provide a prototype.
- if (!FD->hasWrittenPrototype()) {
- TypeSourceInfo *TI = FD->getTypeSourceInfo();
- TypeLoc TL = TI->getTypeLoc();
- FunctionTypeLoc FTL = TL.getAsAdjusted<FunctionTypeLoc>();
- Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 2;
+ // GNU warning -Wstrict-prototypes
+ // Warn if K&R function is defined without a previous declaration.
+ // This warning is issued only if the definition itself does not
+ // provide a prototype. Only K&R definitions do not provide a
+ // prototype.
+ if (!FD->hasWrittenPrototype()) {
+ TypeSourceInfo *TI = FD->getTypeSourceInfo();
+ TypeLoc TL = TI->getTypeLoc();
+ FunctionTypeLoc FTL = TL.getAsAdjusted<FunctionTypeLoc>();
+ Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 2;
+ }
}
- }
- // Warn on CPUDispatch with an actual body.
- if (FD->isMultiVersion() && FD->hasAttr<CPUDispatchAttr>() && Body)
- if (const auto *CmpndBody = dyn_cast<CompoundStmt>(Body))
- if (!CmpndBody->body_empty())
- Diag(CmpndBody->body_front()->getBeginLoc(),
- diag::warn_dispatch_body_ignored);
+ // Warn on CPUDispatch with an actual body.
+ if (FD->isMultiVersion() && FD->hasAttr<CPUDispatchAttr>() && Body)
+ if (const auto *CmpndBody = dyn_cast<CompoundStmt>(Body))
+ if (!CmpndBody->body_empty())
+ Diag(CmpndBody->body_front()->getBeginLoc(),
+ diag::warn_dispatch_body_ignored);
- if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
- const CXXMethodDecl *KeyFunction;
- if (MD->isOutOfLine() && (MD = MD->getCanonicalDecl()) &&
- MD->isVirtual() &&
- (KeyFunction = Context.getCurrentKeyFunction(MD->getParent())) &&
- MD == KeyFunction->getCanonicalDecl()) {
- // Update the key-function state if necessary for this ABI.
- if (FD->isInlined() &&
- !Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline()) {
- Context.setNonKeyFunction(MD);
+ if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ const CXXMethodDecl *KeyFunction;
+ if (MD->isOutOfLine() && (MD = MD->getCanonicalDecl()) &&
+ MD->isVirtual() &&
+ (KeyFunction = Context.getCurrentKeyFunction(MD->getParent())) &&
+ MD == KeyFunction->getCanonicalDecl()) {
+ // Update the key-function state if necessary for this ABI.
+ if (FD->isInlined() &&
+ !Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline()) {
+ Context.setNonKeyFunction(MD);
- // If the newly-chosen key function is already defined, then we
- // need to mark the vtable as used retroactively.
- KeyFunction = Context.getCurrentKeyFunction(MD->getParent());
- const FunctionDecl *Definition;
- if (KeyFunction && KeyFunction->isDefined(Definition))
- MarkVTableUsed(Definition->getLocation(), MD->getParent(), true);
- } else {
- // We just defined they key function; mark the vtable as used.
- MarkVTableUsed(FD->getLocation(), MD->getParent(), true);
+ // If the newly-chosen key function is already defined, then we
+ // need to mark the vtable as used retroactively.
+ KeyFunction = Context.getCurrentKeyFunction(MD->getParent());
+ const FunctionDecl *Definition;
+ if (KeyFunction && KeyFunction->isDefined(Definition))
+ MarkVTableUsed(Definition->getLocation(), MD->getParent(), true);
+ } else {
+ // We just defined they key function; mark the vtable as used.
+ MarkVTableUsed(FD->getLocation(), MD->getParent(), true);
+ }
}
}
- }
- assert((FD == getCurFunctionDecl() || getCurLambda()->CallOperator == FD) &&
- "Function parsing confused");
- } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
- assert(MD == getCurMethodDecl() && "Method parsing confused");
- MD->setBody(Body);
- if (!MD->isInvalidDecl()) {
- DiagnoseSizeOfParametersAndReturnValue(MD->parameters(),
- MD->getReturnType(), MD);
+ assert(
+ (FD == getCurFunctionDecl() || getCurLambda()->CallOperator == FD) &&
+ "Function parsing confused");
+ } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
+ assert(MD == getCurMethodDecl() && "Method parsing confused");
+ MD->setBody(Body);
+ if (!MD->isInvalidDecl()) {
+ DiagnoseSizeOfParametersAndReturnValue(MD->parameters(),
+ MD->getReturnType(), MD);
- if (Body)
- computeNRVO(Body, FSI);
- }
- if (FSI->ObjCShouldCallSuper) {
- Diag(MD->getEndLoc(), diag::warn_objc_missing_super_call)
- << MD->getSelector().getAsString();
- FSI->ObjCShouldCallSuper = false;
- }
- if (FSI->ObjCWarnForNoDesignatedInitChain) {
- const ObjCMethodDecl *InitMethod = nullptr;
- bool isDesignated =
- MD->isDesignatedInitializerForTheInterface(&InitMethod);
- assert(isDesignated && InitMethod);
- (void)isDesignated;
+ if (Body)
+ computeNRVO(Body, FSI);
+ }
+ if (FSI->ObjCShouldCallSuper) {
+ Diag(MD->getEndLoc(), diag::warn_objc_missing_super_call)
+ << MD->getSelector().getAsString();
+ FSI->ObjCShouldCallSuper = false;
+ }
+ if (FSI->ObjCWarnForNoDesignatedInitChain) {
+ const ObjCMethodDecl *InitMethod = nullptr;
+ bool isDesignated =
+ MD->isDesignatedInitializerForTheInterface(&InitMethod);
+ assert(isDesignated && InitMethod);
+ (void)isDesignated;
- auto superIsNSObject = [&](const ObjCMethodDecl *MD) {
- auto IFace = MD->getClassInterface();
- if (!IFace)
- return false;
- auto SuperD = IFace->getSuperClass();
- if (!SuperD)
- return false;
- return SuperD->getIdentifier() ==
- NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject);
- };
- // Don't issue this warning for unavailable inits or direct subclasses
- // of NSObject.
- if (!MD->isUnavailable() && !superIsNSObject(MD)) {
- Diag(MD->getLocation(),
- diag::warn_objc_designated_init_missing_super_call);
- Diag(InitMethod->getLocation(),
- diag::note_objc_designated_init_marked_here);
+ auto superIsNSObject = [&](const ObjCMethodDecl *MD) {
+ auto IFace = MD->getClassInterface();
+ if (!IFace)
+ return false;
+ auto SuperD = IFace->getSuperClass();
+ if (!SuperD)
+ return false;
+ return SuperD->getIdentifier() ==
+ NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject);
+ };
+ // Don't issue this warning for unavailable inits or direct subclasses
+ // of NSObject.
+ if (!MD->isUnavailable() && !superIsNSObject(MD)) {
+ Diag(MD->getLocation(),
+ diag::warn_objc_designated_init_missing_super_call);
+ Diag(InitMethod->getLocation(),
+ diag::note_objc_designated_init_marked_here);
+ }
+ FSI->ObjCWarnForNoDesignatedInitChain = false;
+ }
+ if (FSI->ObjCWarnForNoInitDelegation) {
+ // Don't issue this warning for unavaialable inits.
+ if (!MD->isUnavailable())
+ Diag(MD->getLocation(),
+ diag::warn_objc_secondary_init_missing_init_call);
+ FSI->ObjCWarnForNoInitDelegation = false;
}
- FSI->ObjCWarnForNoDesignatedInitChain = false;
- }
- if (FSI->ObjCWarnForNoInitDelegation) {
- // Don't issue this warning for unavaialable inits.
- if (!MD->isUnavailable())
- Diag(MD->getLocation(),
- diag::warn_objc_secondary_init_missing_init_call);
- FSI->ObjCWarnForNoInitDelegation = false;
- }
- diagnoseImplicitlyRetainedSelf(*this);
- } else {
- // Parsing the function declaration failed in some way. Pop the fake scope
- // we pushed on.
- PopFunctionScopeInfo(ActivePolicy, dcl);
- return nullptr;
- }
+ diagnoseImplicitlyRetainedSelf(*this);
+ } else {
+ // Parsing the function declaration failed in some way. Pop the fake scope
+ // we pushed on.
+ PopFunctionScopeInfo(ActivePolicy, dcl);
+ return nullptr;
+ }
- if (Body && FSI->HasPotentialAvailabilityViolations)
- DiagnoseUnguardedAvailabilityViolations(dcl);
+ if (Body && FSI->HasPotentialAvailabilityViolations)
+ DiagnoseUnguardedAvailabilityViolations(dcl);
- assert(!FSI->ObjCShouldCallSuper &&
- "This should only be set for ObjC methods, which should have been "
- "handled in the block above.");
+ assert(!FSI->ObjCShouldCallSuper &&
+ "This should only be set for ObjC methods, which should have been "
+ "handled in the block above.");
- // Verify and clean out per-function state.
- if (Body && (!FD || !FD->isDefaulted())) {
- // C++ constructors that have function-try-blocks can't have return
- // statements in the handlers of that block. (C++ [except.handle]p14)
- // Verify this.
- if (FD && isa<CXXConstructorDecl>(FD) && isa<CXXTryStmt>(Body))
- DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body));
+ // Verify and clean out per-function state.
+ if (Body && (!FD || !FD->isDefaulted())) {
+ // C++ constructors that have function-try-blocks can't have return
+ // statements in the handlers of that block. (C++ [except.handle]p14)
+ // Verify this.
+ if (FD && isa<CXXConstructorDecl>(FD) && isa<CXXTryStmt>(Body))
+ DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body));
- // Verify that gotos and switch cases don't jump into scopes illegally.
- if (FSI->NeedsScopeChecking() &&
- !PP.isCodeCompletionEnabled())
- DiagnoseInvalidJumps(Body);
+ // Verify that gotos and switch cases don't jump into scopes illegally.
+ if (FSI->NeedsScopeChecking() && !PP.isCodeCompletionEnabled())
+ DiagnoseInvalidJumps(Body);
- if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl)) {
- if (!Destructor->getParent()->isDependentType())
- CheckDestructor(Destructor);
+ if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl)) {
+ if (!Destructor->getParent()->isDependentType())
+ CheckDestructor(Destructor);
- MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
- Destructor->getParent());
- }
+ MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
+ Destructor->getParent());
+ }
- // If any errors have occurred, clear out any temporaries that may have
- // been leftover. This ensures that these temporaries won't be picked up for
- // deletion in some later function.
- if (hasUncompilableErrorOccurred() ||
- getDiagnostics().getSuppressAllDiagnostics()) {
- DiscardCleanupsInEvaluationContext();
- }
- if (!hasUncompilableErrorOccurred() &&
- !isa<FunctionTemplateDecl>(dcl)) {
- // Since the body is valid, issue any analysis-based warnings that are
- // enabled.
- ActivePolicy = &WP;
- }
+ // If any errors have occurred, clear out any temporaries that may have
+ // been leftover. This ensures that these temporaries won't be picked up
+ // for deletion in some later function.
+ if (hasUncompilableErrorOccurred() ||
+ getDiagnostics().getSuppressAllDiagnostics()) {
+ DiscardCleanupsInEvaluationContext();
+ }
+ if (!hasUncompilableErrorOccurred() && !isa<FunctionTemplateDecl>(dcl)) {
+ // Since the body is valid, issue any analysis-based warnings that are
+ // enabled.
+ ActivePolicy = &WP;
+ }
- if (!IsInstantiation && FD && FD->isConstexpr() && !FD->isInvalidDecl() &&
- !CheckConstexprFunctionDefinition(FD, CheckConstexprKind::Diagnose))
- FD->setInvalidDecl();
+ if (!IsInstantiation && FD && FD->isConstexpr() && !FD->isInvalidDecl() &&
+ !CheckConstexprFunctionDefinition(FD, CheckConstexprKind::Diagnose))
+ FD->setInvalidDecl();
- if (FD && FD->hasAttr<NakedAttr>()) {
- for (const Stmt *S : Body->children()) {
- // Allow local register variables without initializer as they don't
- // require prologue.
- bool RegisterVariables = false;
- if (auto *DS = dyn_cast<DeclStmt>(S)) {
- for (const auto *Decl : DS->decls()) {
- if (const auto *Var = dyn_cast<VarDecl>(Decl)) {
- RegisterVariables =
- Var->hasAttr<AsmLabelAttr>() && !Var->hasInit();
- if (!RegisterVariables)
- break;
+ if (FD && FD->hasAttr<NakedAttr>()) {
+ for (const Stmt *S : Body->children()) {
+ // Allow local register variables without initializer as they don't
+ // require prologue.
+ bool RegisterVariables = false;
+ if (auto *DS = dyn_cast<DeclStmt>(S)) {
+ for (const auto *Decl : DS->decls()) {
+ if (const auto *Var = dyn_cast<VarDecl>(Decl)) {
+ RegisterVariables =
+ Var->hasAttr<AsmLabelAttr>() && !Var->hasInit();
+ if (!RegisterVariables)
+ break;
+ }
}
}
- }
- if (RegisterVariables)
- continue;
- if (!isa<AsmStmt>(S) && !isa<NullStmt>(S)) {
- Diag(S->getBeginLoc(), diag::err_non_asm_stmt_in_naked_function);
- Diag(FD->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
- FD->setInvalidDecl();
- break;
+ if (RegisterVariables)
+ continue;
+ if (!isa<AsmStmt>(S) && !isa<NullStmt>(S)) {
+ Diag(S->getBeginLoc(), diag::err_non_asm_stmt_in_naked_function);
+ Diag(FD->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
+ FD->setInvalidDecl();
+ break;
+ }
}
}
- }
- assert(ExprCleanupObjects.size() ==
- ExprEvalContexts.back().NumCleanupObjects &&
- "Leftover temporaries in function");
- assert(!Cleanup.exprNeedsCleanups() && "Unaccounted cleanups in function");
- assert(MaybeODRUseExprs.empty() &&
- "Leftover expressions for odr-use checking");
- }
+ assert(ExprCleanupObjects.size() ==
+ ExprEvalContexts.back().NumCleanupObjects &&
+ "Leftover temporaries in function");
+ assert(!Cleanup.exprNeedsCleanups() &&
+ "Unaccounted cleanups in function");
+ assert(MaybeODRUseExprs.empty() &&
+ "Leftover expressions for odr-use checking");
+ }
+ } // Pops the ExitFunctionBodyRAII scope, which needs to happen before we pop
+ // the declaration context below. Otherwise, we're unable to transform
+ // 'this' expressions when transforming immediate context functions.
if (!IsInstantiation)
PopDeclContext();
@@ -14825,13 +14852,18 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
DiscardCleanupsInEvaluationContext();
}
- if (FD && (LangOpts.OpenMP || LangOpts.CUDA || LangOpts.SYCLIsDevice)) {
+ if (FD && ((LangOpts.OpenMP && (LangOpts.OpenMPIsDevice ||
+ !LangOpts.OMPTargetTriples.empty())) ||
+ LangOpts.CUDA || LangOpts.SYCLIsDevice)) {
auto ES = getEmissionStatus(FD);
if (ES == Sema::FunctionEmissionStatus::Emitted ||
ES == Sema::FunctionEmissionStatus::Unknown)
DeclsToCheckForDeferredDiags.insert(FD);
}
+ if (FD && !FD->isDeleted())
+ checkTypeSupport(FD->getType(), FD->getLocation(), FD);
+
return dcl;
}
@@ -15132,6 +15164,34 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
else
FD->addAttr(CUDAHostAttr::CreateImplicit(Context, FD->getLocation()));
}
+
+ // Add known guaranteed alignment for allocation functions.
+ switch (BuiltinID) {
+ case Builtin::BIaligned_alloc:
+ if (!FD->hasAttr<AllocAlignAttr>())
+ FD->addAttr(AllocAlignAttr::CreateImplicit(Context, ParamIdx(1, FD),
+ FD->getLocation()));
+ LLVM_FALLTHROUGH;
+ case Builtin::BIcalloc:
+ case Builtin::BImalloc:
+ case Builtin::BImemalign:
+ case Builtin::BIrealloc:
+ case Builtin::BIstrdup:
+ case Builtin::BIstrndup: {
+ if (!FD->hasAttr<AssumeAlignedAttr>()) {
+ unsigned NewAlign = Context.getTargetInfo().getNewAlign() /
+ Context.getTargetInfo().getCharWidth();
+ IntegerLiteral *Alignment = IntegerLiteral::Create(
+ Context, Context.MakeIntValue(NewAlign, Context.UnsignedIntTy),
+ Context.UnsignedIntTy, FD->getLocation());
+ FD->addAttr(AssumeAlignedAttr::CreateImplicit(
+ Context, Alignment, /*Offset=*/nullptr, FD->getLocation()));
+ }
+ break;
+ }
+ default:
+ break;
+ }
}
AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(FD);
@@ -16569,6 +16629,23 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD,
// Notify the consumer that we've defined a tag.
if (!Tag->isInvalidDecl())
Consumer.HandleTagDeclDefinition(Tag);
+
+ // Clangs implementation of #pragma align(packed) differs in bitfield layout
+ // from XLs and instead matches the XL #pragma pack(1) behavior.
+ if (Context.getTargetInfo().getTriple().isOSAIX() &&
+ AlignPackStack.hasValue()) {
+ AlignPackInfo APInfo = AlignPackStack.CurrentValue;
+ // Only diagnose #pragma align(packed).
+ if (!APInfo.IsAlignAttr() || APInfo.getAlignMode() != AlignPackInfo::Packed)
+ return;
+ const RecordDecl *RD = dyn_cast<RecordDecl>(Tag);
+ if (!RD)
+ return;
+ // Only warn if there is at least 1 bitfield member.
+ if (llvm::any_of(RD->fields(),
+ [](const FieldDecl *FD) { return FD->isBitField(); }))
+ Diag(BraceRange.getBegin(), diag::warn_pragma_align_not_xl_compatible);
+ }
}
void Sema::ActOnObjCContainerFinishDefinition() {
@@ -17743,7 +17820,8 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
Val = DefaultLvalueConversion(Val).get();
if (Val) {
- if (Enum->isDependentType() || Val->isTypeDependent())
+ if (Enum->isDependentType() || Val->isTypeDependent() ||
+ Val->containsErrors())
EltTy = Context.DependentTy;
else {
// FIXME: We don't allow folding in C++11 mode for an enum with a fixed