aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp1142
1 files changed, 628 insertions, 514 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp
index 5b0417fa8859..1f7ab49ccdd7 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp
@@ -255,7 +255,7 @@ static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
// We found some types in dependent base classes. Recover as if the user
// wrote 'typename MyClass::II' instead of 'II'. We'll fully resolve the
// lookup during template instantiation.
- S.Diag(NameLoc, diag::ext_found_via_dependent_bases_lookup) << &II;
+ S.Diag(NameLoc, diag::ext_found_in_dependent_base) << &II;
ASTContext &Context = S.Context;
auto *NNS = NestedNameSpecifier::Create(Context, nullptr, false,
@@ -436,9 +436,7 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
Res != ResEnd; ++Res) {
if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res) ||
(AllowDeducedTemplate && getAsTypeTemplateDecl(*Res))) {
- if (!IIDecl ||
- (*Res)->getLocation().getRawEncoding() <
- IIDecl->getLocation().getRawEncoding())
+ if (!IIDecl || (*Res)->getLocation() < IIDecl->getLocation())
IIDecl = *Res;
}
}
@@ -1184,23 +1182,20 @@ Corrected:
return ParsedType::make(T);
}
- // FIXME: This is context-dependent. We need to defer building the member
- // expression until the classification is consumed.
- if (FirstDecl->isCXXClassMember())
- return NameClassification::ContextIndependentExpr(
- BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, nullptr,
- S));
-
// If we already know which single declaration is referenced, just annotate
- // that declaration directly.
+ // that declaration directly. Defer resolving even non-overloaded class
+ // member accesses, as we need to defer certain access checks until we know
+ // the context.
bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren));
- if (Result.isSingleResult() && !ADL)
+ if (Result.isSingleResult() && !ADL && !FirstDecl->isCXXClassMember())
return NameClassification::NonType(Result.getRepresentativeDecl());
- // Build an UnresolvedLookupExpr. Note that this doesn't depend on the
- // context in which we performed classification, so it's safe to do now.
- return NameClassification::ContextIndependentExpr(
- BuildDeclarationNameExpr(SS, Result, ADL));
+ // Otherwise, this is an overload set that we will need to resolve later.
+ Result.suppressDiagnostics();
+ return NameClassification::OverloadSet(UnresolvedLookupExpr::Create(
+ Context, Result.getNamingClass(), SS.getWithLocInContext(Context),
+ Result.getLookupNameInfo(), ADL, Result.isOverloadedResult(),
+ Result.begin(), Result.end()));
}
ExprResult
@@ -1240,6 +1235,30 @@ ExprResult Sema::ActOnNameClassifiedAsNonType(Scope *S, const CXXScopeSpec &SS,
return BuildDeclarationNameExpr(SS, Result, ADL);
}
+ExprResult Sema::ActOnNameClassifiedAsOverloadSet(Scope *S, Expr *E) {
+ // For an implicit class member access, transform the result into a member
+ // access expression if necessary.
+ auto *ULE = cast<UnresolvedLookupExpr>(E);
+ if ((*ULE->decls_begin())->isCXXClassMember()) {
+ CXXScopeSpec SS;
+ SS.Adopt(ULE->getQualifierLoc());
+
+ // Reconstruct the lookup result.
+ LookupResult Result(*this, ULE->getName(), ULE->getNameLoc(),
+ LookupOrdinaryName);
+ Result.setNamingClass(ULE->getNamingClass());
+ for (auto I = ULE->decls_begin(), E = ULE->decls_end(); I != E; ++I)
+ Result.addDecl(*I, I.getAccess());
+ Result.resolveKind();
+ return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result,
+ nullptr, S);
+ }
+
+ // Otherwise, this is already in the form we needed, and no further checks
+ // are necessary.
+ return ULE;
+}
+
Sema::TemplateNameKindForDiagnostics
Sema::getTemplateNameKindForDiagnostics(TemplateName Name) {
auto *TD = Name.getAsTemplateDecl();
@@ -1457,10 +1476,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
// Out-of-line definitions shouldn't be pushed into scope in C++, unless they
// are function-local declarations.
- if (getLangOpts().CPlusPlus && D->isOutOfLine() &&
- !D->getDeclContext()->getRedeclContext()->Equals(
- D->getLexicalDeclContext()->getRedeclContext()) &&
- !D->getLexicalDeclContext()->isFunctionOrMethod())
+ if (getLangOpts().CPlusPlus && D->isOutOfLine() && !S->getFnParent())
return;
// Template instantiations should also not be pushed into scope.
@@ -1742,25 +1758,20 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
if (D->isInvalidDecl())
return false;
- bool Referenced = false;
if (auto *DD = dyn_cast<DecompositionDecl>(D)) {
// For a decomposition declaration, warn if none of the bindings are
// referenced, instead of if the variable itself is referenced (which
// it is, by the bindings' expressions).
- for (auto *BD : DD->bindings()) {
- if (BD->isReferenced()) {
- Referenced = true;
- break;
- }
- }
+ for (auto *BD : DD->bindings())
+ if (BD->isReferenced())
+ return false;
} else if (!D->getDeclName()) {
return false;
} else if (D->isReferenced() || D->isUsed()) {
- Referenced = true;
+ return false;
}
- if (Referenced || D->hasAttr<UnusedAttr>() ||
- D->hasAttr<ObjCPreciseLifetimeAttr>())
+ if (D->hasAttr<UnusedAttr>() || D->hasAttr<ObjCPreciseLifetimeAttr>())
return false;
if (isa<LabelDecl>(D))
@@ -1905,7 +1916,7 @@ static void CheckPoppedLabel(LabelDecl *L, Sema &S) {
else
Diagnose = L->getStmt() == nullptr;
if (Diagnose)
- S.Diag(L->getLocation(), diag::err_undeclared_label_use) <<L->getDeclName();
+ S.Diag(L->getLocation(), diag::err_undeclared_label_use) << L;
}
void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
@@ -2019,24 +2030,6 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) {
return S;
}
-/// Looks up the declaration of "struct objc_super" and
-/// saves it for later use in building builtin declaration of
-/// objc_msgSendSuper and objc_msgSendSuper_stret. If no such
-/// pre-existing declaration exists no action takes place.
-static void LookupPredefedObjCSuperType(Sema &ThisSema, Scope *S,
- IdentifierInfo *II) {
- if (!II->isStr("objc_msgSendSuper"))
- return;
- ASTContext &Context = ThisSema.Context;
-
- LookupResult Result(ThisSema, &Context.Idents.get("objc_super"),
- SourceLocation(), Sema::LookupTagName);
- ThisSema.LookupName(Result, S);
- if (Result.getResultKind() == LookupResult::Found)
- if (const TagDecl *TD = Result.getAsSingle<TagDecl>())
- Context.setObjCSuperType(Context.getTagDeclType(TD));
-}
-
static StringRef getHeaderName(Builtin::Context &BuiltinInfo, unsigned ID,
ASTContext::GetBuiltinTypeError Error) {
switch (Error) {
@@ -2097,7 +2090,7 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, QualType Type,
NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
Scope *S, bool ForRedeclaration,
SourceLocation Loc) {
- LookupPredefedObjCSuperType(*this, S, II);
+ LookupNecessaryTypesForBuiltin(S, ID);
ASTContext::GetBuiltinTypeError Error;
QualType R = Context.GetBuiltinType(ID, Error);
@@ -2593,6 +2586,8 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
return false;
} else if (const auto *MA = dyn_cast<MinSizeAttr>(Attr))
NewAttr = S.mergeMinSizeAttr(D, *MA);
+ else if (const auto *SNA = dyn_cast<SwiftNameAttr>(Attr))
+ NewAttr = S.mergeSwiftNameAttr(D, *SNA, SNA->getName());
else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr))
NewAttr = S.mergeOptimizeNoneAttr(D, *OA);
else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr))
@@ -2617,6 +2612,10 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
NewAttr = S.mergeImportModuleAttr(D, *IMA);
else if (const auto *INA = dyn_cast<WebAssemblyImportNameAttr>(Attr))
NewAttr = S.mergeImportNameAttr(D, *INA);
+ else if (const auto *TCBA = dyn_cast<EnforceTCBAttr>(Attr))
+ NewAttr = S.mergeEnforceTCBAttr(D, *TCBA);
+ else if (const auto *TCBLA = dyn_cast<EnforceTCBLeafAttr>(Attr))
+ NewAttr = S.mergeEnforceTCBLeafAttr(D, *TCBLA);
else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr))
NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
@@ -2640,8 +2639,11 @@ static const NamedDecl *getDefinition(const Decl *D) {
return Def;
return VD->getActingDefinition();
}
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- return FD->getDefinition();
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ const FunctionDecl *Def = nullptr;
+ if (FD->isDefined(Def, true))
+ return Def;
+ }
return nullptr;
}
@@ -3236,6 +3238,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
}
}
+ // If the old declaration was found in an inline namespace and the new
+ // declaration was qualified, update the DeclContext to match.
+ adjustDeclContextForDeclaratorDecl(New, Old);
+
// If the old declaration is invalid, just give up here.
if (Old->isInvalidDecl())
return true;
@@ -4050,6 +4056,10 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
return New->setInvalidDecl();
}
+ // If the old declaration was found in an inline namespace and the new
+ // declaration was qualified, update the DeclContext to match.
+ adjustDeclContextForDeclaratorDecl(New, Old);
+
// Ensure the template parameters are compatible.
if (NewTemplate &&
!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
@@ -4234,7 +4244,6 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
New->setPreviousDecl(Old);
if (NewTemplate)
NewTemplate->setPreviousDecl(OldTemplate);
- adjustDeclContextForDeclaratorDecl(New, Old);
// Inherit access appropriately.
New->setAccess(Old->getAccess());
@@ -4599,10 +4608,10 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
if (Tag)
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag)
<< GetDiagnosticTypeSpecifierID(DS.getTypeSpecType())
- << DS.getConstexprSpecifier();
+ << static_cast<int>(DS.getConstexprSpecifier());
else
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_wrong_decl_kind)
- << DS.getConstexprSpecifier();
+ << static_cast<int>(DS.getConstexprSpecifier());
// Don't emit warnings after this error.
return TagD;
}
@@ -4738,7 +4747,10 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
if (!DeclaresAnything) {
// In C, we allow this as a (popular) extension / bug. Don't bother
// producing further diagnostics for redundant qualifiers after this.
- Diag(DS.getBeginLoc(), diag::ext_no_declarators) << DS.getSourceRange();
+ Diag(DS.getBeginLoc(), (IsExplicitInstantiation || !TemplateParams.empty())
+ ? diag::err_no_declarators
+ : diag::ext_no_declarators)
+ << DS.getSourceRange();
return TagD;
}
@@ -5157,7 +5169,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
Diag(DS.getBeginLoc(), diag::ext_no_declarators) << DS.getSourceRange();
// Mock up a declarator.
- Declarator Dc(DS, DeclaratorContext::MemberContext);
+ Declarator Dc(DS, DeclaratorContext::Member);
TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
assert(TInfo && "couldn't build declarator info for anonymous struct/union");
@@ -5254,7 +5266,7 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
assert(Record && "expected a record!");
// Mock up a declarator.
- Declarator Dc(DS, DeclaratorContext::TypeNameContext);
+ Declarator Dc(DS, DeclaratorContext::TypeName);
TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
assert(TInfo && "couldn't build declarator info for anonymous struct");
@@ -5339,8 +5351,8 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
case UnqualifiedIdKind::IK_OperatorFunctionId:
NameInfo.setName(Context.DeclarationNames.getCXXOperatorName(
Name.OperatorFunctionId.Operator));
- NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc
- = Name.OperatorFunctionId.SymbolLocations[0];
+ NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc =
+ Name.OperatorFunctionId.SymbolLocations[0].getRawEncoding();
NameInfo.getInfo().CXXOperatorName.EndOpNameLoc
= Name.EndLocation.getRawEncoding();
return NameInfo;
@@ -5488,7 +5500,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
// Grab the type from the parser.
TypeSourceInfo *TSI = nullptr;
QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI);
- if (T.isNull() || !T->isDependentType()) break;
+ if (T.isNull() || !T->isInstantiationDependentType()) break;
// Make sure there's a type source info. This isn't really much
// of a waste; most dependent types should have type source info
@@ -5540,7 +5552,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
}
Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) {
- D.setFunctionDefinitionKind(FDK_Declaration);
+ D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
Decl *Dcl = HandleDeclarator(S, D, MultiTemplateParamsArg());
if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer() &&
@@ -5929,9 +5941,14 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
if (!VLATy)
return QualType();
- // FIXME: We should probably handle this case
- if (VLATy->getElementType()->isVariablyModifiedType())
- return QualType();
+
+ QualType ElemTy = VLATy->getElementType();
+ if (ElemTy->isVariablyModifiedType()) {
+ ElemTy = TryToFixInvalidVariablyModifiedType(ElemTy, Context,
+ SizeIsNegative, Oversized);
+ if (ElemTy.isNull())
+ return QualType();
+ }
Expr::EvalResult Result;
if (!VLATy->getSizeExpr() ||
@@ -5947,16 +5964,19 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
}
// Check whether the array is too large to be addressed.
- unsigned ActiveSizeBits
- = ConstantArrayType::getNumAddressingBits(Context, VLATy->getElementType(),
- Res);
+ unsigned ActiveSizeBits =
+ (!ElemTy->isDependentType() && !ElemTy->isVariablyModifiedType() &&
+ !ElemTy->isIncompleteType() && !ElemTy->isUndeducedType())
+ ? ConstantArrayType::getNumAddressingBits(Context, ElemTy, Res)
+ : Res.getActiveBits();
if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
Oversized = Res;
return QualType();
}
- return Context.getConstantArrayType(
- VLATy->getElementType(), Res, VLATy->getSizeExpr(), ArrayType::Normal, 0);
+ QualType FoldedArrayType = Context.getConstantArrayType(
+ ElemTy, Res, VLATy->getSizeExpr(), ArrayType::Normal, 0);
+ return Qs.apply(Context, FoldedArrayType);
}
static void
@@ -5982,7 +6002,13 @@ FixInvalidVariablyModifiedTypeLoc(TypeLoc SrcTL, TypeLoc DstTL) {
ArrayTypeLoc DstATL = DstTL.castAs<ArrayTypeLoc>();
TypeLoc SrcElemTL = SrcATL.getElementLoc();
TypeLoc DstElemTL = DstATL.getElementLoc();
- DstElemTL.initializeFullCopy(SrcElemTL);
+ if (VariableArrayTypeLoc SrcElemATL =
+ SrcElemTL.getAs<VariableArrayTypeLoc>()) {
+ ConstantArrayTypeLoc DstElemATL = DstElemTL.castAs<ConstantArrayTypeLoc>();
+ FixInvalidVariablyModifiedTypeLoc(SrcElemATL, DstElemATL);
+ } else {
+ DstElemTL.initializeFullCopy(SrcElemTL);
+ }
DstATL.setLBracketLoc(SrcATL.getLBracketLoc());
DstATL.setSizeExpr(SrcATL.getSizeExpr());
DstATL.setRBracketLoc(SrcATL.getRBracketLoc());
@@ -6007,6 +6033,31 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo,
return FixedTInfo;
}
+/// Attempt to fold a variable-sized type to a constant-sized type, returning
+/// true if we were successful.
+static bool tryToFixVariablyModifiedVarType(Sema &S, TypeSourceInfo *&TInfo,
+ QualType &T, SourceLocation Loc,
+ unsigned FailedFoldDiagID) {
+ bool SizeIsNegative;
+ llvm::APSInt Oversized;
+ TypeSourceInfo *FixedTInfo = TryToFixInvalidVariablyModifiedTypeSourceInfo(
+ TInfo, S.Context, SizeIsNegative, Oversized);
+ if (FixedTInfo) {
+ S.Diag(Loc, diag::ext_vla_folded_to_constant);
+ TInfo = FixedTInfo;
+ T = FixedTInfo->getType();
+ return true;
+ }
+
+ if (SizeIsNegative)
+ S.Diag(Loc, diag::err_typecheck_negative_array_size);
+ else if (Oversized.getBoolValue())
+ S.Diag(Loc, diag::err_array_too_large) << Oversized.toString(10);
+ else if (FailedFoldDiagID)
+ S.Diag(Loc, FailedFoldDiagID);
+ return false;
+}
+
/// Register the given locally-scoped extern "C" declaration so
/// that it can be found later for redeclarations. We include any extern "C"
/// declaration that is not visible in the translation unit here, not just
@@ -6066,7 +6117,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
<< getLangOpts().CPlusPlus17;
if (D.getDeclSpec().hasConstexprSpecifier())
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
- << 1 << D.getDeclSpec().getConstexprSpecifier();
+ << 1 << static_cast<int>(D.getDeclSpec().getConstexprSpecifier());
if (D.getName().Kind != UnqualifiedIdKind::IK_Identifier) {
if (D.getName().Kind == UnqualifiedIdKind::IK_DeductionGuideName)
@@ -6112,7 +6163,7 @@ Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) {
SizeIsNegative,
Oversized);
if (FixedTInfo) {
- Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size);
+ Diag(NewTD->getLocation(), diag::ext_vla_folded_to_constant);
NewTD->setTypeSourceInfo(FixedTInfo);
} else {
if (SizeIsNegative)
@@ -6494,7 +6545,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
// special MSVC extension: in the last case, the declaration is treated as if
// it were marked dllexport.
bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false;
- bool IsMicrosoft = S.Context.getTargetInfo().getCXXABI().isMicrosoft();
+ bool IsMicrosoftABI = S.Context.getTargetInfo().shouldDLLImportComdatSymbols();
if (const auto *VD = dyn_cast<VarDecl>(NewDecl)) {
// Ignore static data because out-of-line definitions are diagnosed
// separately.
@@ -6508,9 +6559,9 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
}
if (OldImportAttr && !HasNewAttr &&
- (!IsInline || (IsMicrosoft && IsTemplate)) && !IsStaticDataMember &&
+ (!IsInline || (IsMicrosoftABI && IsTemplate)) && !IsStaticDataMember &&
!NewDecl->isLocalExternDecl() && !IsQualifiedFriend) {
- if (IsMicrosoft && IsDefinition) {
+ if (IsMicrosoftABI && IsDefinition) {
S.Diag(NewDecl->getLocation(),
diag::warn_redeclaration_without_import_attribute)
<< NewDecl;
@@ -6527,7 +6578,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
OldDecl->dropAttr<DLLImportAttr>();
NewDecl->dropAttr<DLLImportAttr>();
}
- } else if (IsInline && OldImportAttr && !IsMicrosoft) {
+ } else if (IsInline && OldImportAttr && !IsMicrosoftABI) {
// In MinGW, seeing a function declared inline drops the dllimport
// attribute.
OldDecl->dropAttr<DLLImportAttr>();
@@ -6706,14 +6757,16 @@ static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D,
}
// OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed.
- QualType NR = R;
- while (NR->isPointerType()) {
- if (NR->isFunctionPointerType()) {
- Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer);
- D.setInvalidType();
- return false;
+ if (!Se.getOpenCLOptions().isEnabled("__cl_clang_function_pointers")) {
+ QualType NR = R;
+ while (NR->isPointerType() || NR->isMemberFunctionPointerType()) {
+ if (NR->isFunctionPointerType() || NR->isMemberFunctionPointerType()) {
+ Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer);
+ D.setInvalidType();
+ return false;
+ }
+ NR = NR->getPointeeType();
}
- NR = NR->getPointeeType();
}
if (!Se.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
@@ -6845,6 +6898,12 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
+ // If this variable has a variable-modified type and an initializer, try to
+ // fold to a constant-sized type. This is otherwise invalid.
+ if (D.hasInitializer() && R->isVariablyModifiedType())
+ tryToFixVariablyModifiedVarType(*this, TInfo, R, D.getIdentifierLoc(),
+ /*DiagID=*/0);
+
bool IsMemberSpecialization = false;
bool IsVariableTemplateSpecialization = false;
bool IsPartialSpecialization = false;
@@ -6963,19 +7022,18 @@ NamedDecl *Sema::ActOnVariableDeclarator(
TemplateParams->getRAngleLoc());
TemplateParams = nullptr;
} else {
+ // Check that we can declare a template here.
+ if (CheckTemplateDeclScope(S, TemplateParams))
+ return nullptr;
+
if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
// This is an explicit specialization or a partial specialization.
- // FIXME: Check that we can declare a specialization here.
IsVariableTemplateSpecialization = true;
IsPartialSpecialization = TemplateParams->size() > 0;
} else { // if (TemplateParams->size() > 0)
// This is a template declaration.
IsVariableTemplate = true;
- // Check that we can declare a template here.
- if (CheckTemplateDeclScope(S, TemplateParams))
- return nullptr;
-
// Only C++1y supports variable templates (N3651).
Diag(D.getIdentifierLoc(),
getLangOpts().CPlusPlus14
@@ -6984,6 +7042,10 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
} else {
+ // Check that we can declare a member specialization here.
+ if (!TemplateParamLists.empty() && IsMemberSpecialization &&
+ CheckTemplateDeclScope(S, TemplateParamLists.back()))
+ return nullptr;
assert((Invalid ||
D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) &&
"should have a 'template<>' for this decl");
@@ -7103,16 +7165,16 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
switch (D.getDeclSpec().getConstexprSpecifier()) {
- case CSK_unspecified:
+ case ConstexprSpecKind::Unspecified:
break;
- case CSK_consteval:
+ case ConstexprSpecKind::Consteval:
Diag(D.getDeclSpec().getConstexprSpecLoc(),
- diag::err_constexpr_wrong_decl_kind)
- << D.getDeclSpec().getConstexprSpecifier();
+ diag::err_constexpr_wrong_decl_kind)
+ << static_cast<int>(D.getDeclSpec().getConstexprSpecifier());
LLVM_FALLTHROUGH;
- case CSK_constexpr:
+ case ConstexprSpecKind::Constexpr:
NewVD->setConstexpr(true);
MaybeAddCUDAConstantAttr(NewVD);
// C++1z [dcl.spec.constexpr]p1:
@@ -7124,7 +7186,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
NewVD->setImplicitlyInline();
break;
- case CSK_constinit:
+ case ConstexprSpecKind::Constinit:
if (!NewVD->hasGlobalStorage())
Diag(D.getDeclSpec().getConstexprSpecLoc(),
diag::err_constinit_local_variable);
@@ -7166,9 +7228,10 @@ NamedDecl *Sema::ActOnVariableDeclarator(
<< FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
else if (NewVD->hasLocalStorage())
Diag(NewVD->getLocation(), diag::err_module_private_local)
- << 0 << NewVD->getDeclName()
- << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
- << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
+ << 0 << NewVD
+ << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
+ << FixItHint::CreateRemoval(
+ D.getDeclSpec().getModulePrivateSpecLoc());
else {
NewVD->setModulePrivate();
if (NewTemplate)
@@ -7975,7 +8038,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
return;
}
- Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
+ Diag(NewVD->getLocation(), diag::ext_vla_folded_to_constant);
NewVD->setType(FixedT);
NewVD->setTypeSourceInfo(FixedTInfo);
}
@@ -8015,6 +8078,14 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
NewVD->setInvalidDecl();
return;
}
+
+ // PPC MMA non-pointer types are not allowed as non-local variable types.
+ if (Context.getTargetInfo().getTriple().isPPC64() &&
+ !NewVD->isLocalVarDecl() &&
+ CheckPPCMMAType(T, NewVD->getLocation())) {
+ NewVD->setInvalidDecl();
+ return;
+ }
}
/// Perform semantic checking on a newly-created variable
@@ -8049,73 +8120,54 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) {
return false;
}
-namespace {
-struct FindOverriddenMethod {
- Sema *S;
- CXXMethodDecl *Method;
-
- /// Member lookup function that determines whether a given C++
- /// method overrides a method in a base class, to be used with
- /// CXXRecordDecl::lookupInBases().
- bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
- RecordDecl *BaseRecord =
- Specifier->getType()->castAs<RecordType>()->getDecl();
+/// AddOverriddenMethods - See if a method overrides any in the base classes,
+/// and if so, check that it's a valid override and remember it.
+bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
+ llvm::SmallPtrSet<const CXXMethodDecl*, 4> Overridden;
- DeclarationName Name = Method->getDeclName();
+ // Look for methods in base classes that this method might override.
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false,
+ /*DetectVirtual=*/false);
+ auto VisitBase = [&] (const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ CXXRecordDecl *BaseRecord = Specifier->getType()->getAsCXXRecordDecl();
+ DeclarationName Name = MD->getDeclName();
- // FIXME: Do we care about other names here too?
if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
// We really want to find the base class destructor here.
- QualType T = S->Context.getTypeDeclType(BaseRecord);
- CanQualType CT = S->Context.getCanonicalType(T);
-
- Name = S->Context.DeclarationNames.getCXXDestructorName(CT);
- }
-
- for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
- Path.Decls = Path.Decls.slice(1)) {
- NamedDecl *D = Path.Decls.front();
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
- if (MD->isVirtual() &&
- !S->IsOverload(
- Method, MD, /*UseMemberUsingDeclRules=*/false,
- /*ConsiderCudaAttrs=*/true,
- // C++2a [class.virtual]p2 does not consider requires clauses
- // when overriding.
- /*ConsiderRequiresClauses=*/false))
- return true;
+ QualType T = Context.getTypeDeclType(BaseRecord);
+ CanQualType CT = Context.getCanonicalType(T);
+ Name = Context.DeclarationNames.getCXXDestructorName(CT);
+ }
+
+ for (NamedDecl *BaseND : BaseRecord->lookup(Name)) {
+ CXXMethodDecl *BaseMD =
+ dyn_cast<CXXMethodDecl>(BaseND->getCanonicalDecl());
+ if (!BaseMD || !BaseMD->isVirtual() ||
+ IsOverload(MD, BaseMD, /*UseMemberUsingDeclRules=*/false,
+ /*ConsiderCudaAttrs=*/true,
+ // C++2a [class.virtual]p2 does not consider requires
+ // clauses when overriding.
+ /*ConsiderRequiresClauses=*/false))
+ continue;
+
+ if (Overridden.insert(BaseMD).second) {
+ MD->addOverriddenMethod(BaseMD);
+ CheckOverridingFunctionReturnType(MD, BaseMD);
+ CheckOverridingFunctionAttributes(MD, BaseMD);
+ CheckOverridingFunctionExceptionSpec(MD, BaseMD);
+ CheckIfOverriddenFunctionIsMarkedFinal(MD, BaseMD);
}
+
+ // A method can only override one function from each base class. We
+ // don't track indirectly overridden methods from bases of bases.
+ return true;
}
return false;
- }
-};
-} // end anonymous namespace
-
-/// AddOverriddenMethods - See if a method overrides any in the base classes,
-/// and if so, check that it's a valid override and remember it.
-bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
- // Look for methods in base classes that this method might override.
- CXXBasePaths Paths;
- FindOverriddenMethod FOM;
- FOM.Method = MD;
- FOM.S = this;
- bool AddedAny = false;
- if (DC->lookupInBases(FOM, Paths)) {
- for (auto *I : Paths.found_decls()) {
- if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(I)) {
- MD->addOverriddenMethod(OldMD->getCanonicalDecl());
- if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
- !CheckOverridingFunctionAttributes(MD, OldMD) &&
- !CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
- !CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) {
- AddedAny = true;
- }
- }
- }
- }
+ };
- return AddedAny;
+ DC->lookupInBases(VisitBase, Paths);
+ return !Overridden.empty();
}
namespace {
@@ -8394,7 +8446,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
NewFD = FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo,
R, TInfo, SC, isInline, HasPrototype,
- CSK_unspecified,
+ ConstexprSpecKind::Unspecified,
/*TrailingRequiresClause=*/nullptr);
if (D.isInvalidType())
NewFD->setInvalidDecl();
@@ -8405,11 +8457,11 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
ExplicitSpecifier ExplicitSpecifier = D.getDeclSpec().getExplicitSpecifier();
ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier();
- if (ConstexprKind == CSK_constinit) {
+ if (ConstexprKind == ConstexprSpecKind::Constinit) {
SemaRef.Diag(D.getDeclSpec().getConstexprSpecLoc(),
diag::err_constexpr_wrong_decl_kind)
- << ConstexprKind;
- ConstexprKind = CSK_unspecified;
+ << static_cast<int>(ConstexprKind);
+ ConstexprKind = ConstexprSpecKind::Unspecified;
D.getMutableDeclSpec().ClearConstexprSpec();
}
Expr *TrailingRequiresClause = D.getTrailingRequiresClause();
@@ -8563,12 +8615,21 @@ static bool isOpenCLSizeDependentType(ASTContext &C, QualType Ty) {
static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
if (PT->isPointerType()) {
QualType PointeeType = PT->getPointeeType();
- if (PointeeType->isPointerType())
- return PtrPtrKernelParam;
if (PointeeType.getAddressSpace() == LangAS::opencl_generic ||
PointeeType.getAddressSpace() == LangAS::opencl_private ||
PointeeType.getAddressSpace() == LangAS::Default)
return InvalidAddrSpacePtrKernelParam;
+
+ if (PointeeType->isPointerType()) {
+ // This is a pointer to pointer parameter.
+ // Recursively check inner type.
+ OpenCLParamType ParamKind = getOpenCLKernelParameterType(S, PointeeType);
+ if (ParamKind == InvalidAddrSpacePtrKernelParam ||
+ ParamKind == InvalidKernelParam)
+ return ParamKind;
+
+ return PtrPtrKernelParam;
+ }
return PtrKernelParam;
}
@@ -8621,11 +8682,17 @@ static void checkIsValidOpenCLKernelParameter(
switch (getOpenCLKernelParameterType(S, PT)) {
case PtrPtrKernelParam:
- // OpenCL v1.2 s6.9.a:
- // A kernel function argument cannot be declared as a
- // pointer to a pointer type.
- S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param);
- D.setInvalidType();
+ // 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) {
+ S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param);
+ D.setInvalidType();
+ return;
+ }
+
+ ValidTypes.insert(PT.getTypePtr());
return;
case InvalidAddrSpacePtrKernelParam:
@@ -8909,13 +8976,13 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TemplateParamLists, isFriend, isMemberSpecialization,
Invalid);
if (TemplateParams) {
+ // Check that we can declare a template here.
+ if (CheckTemplateDeclScope(S, TemplateParams))
+ NewFD->setInvalidDecl();
+
if (TemplateParams->size() > 0) {
// This is a function template
- // Check that we can declare a template here.
- if (CheckTemplateDeclScope(S, TemplateParams))
- NewFD->setInvalidDecl();
-
// A destructor cannot be a template.
if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
Diag(NewFD->getLocation(), diag::err_destructor_template);
@@ -8974,6 +9041,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
} else {
+ // Check that we can declare a template here.
+ if (!TemplateParamLists.empty() && isMemberSpecialization &&
+ CheckTemplateDeclScope(S, TemplateParamLists.back()))
+ NewFD->setInvalidDecl();
+
// All template param lists were matched against the scope specifier:
// this is NOT (an explicit specialization of) a template.
if (TemplateParamLists.size() > 0)
@@ -9068,8 +9140,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
- if (ConstexprSpecKind ConstexprKind =
- D.getDeclSpec().getConstexprSpecifier()) {
+ ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier();
+ if (ConstexprKind != ConstexprSpecKind::Unspecified) {
// C++11 [dcl.constexpr]p2: constexpr functions and constexpr constructors
// are implicitly inline.
NewFD->setImplicitlyInline();
@@ -9078,15 +9150,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// be either constructors or to return a literal type. Therefore,
// destructors cannot be declared constexpr.
if (isa<CXXDestructorDecl>(NewFD) &&
- (!getLangOpts().CPlusPlus20 || ConstexprKind == CSK_consteval)) {
+ (!getLangOpts().CPlusPlus20 ||
+ ConstexprKind == ConstexprSpecKind::Consteval)) {
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor)
- << ConstexprKind;
- NewFD->setConstexprKind(getLangOpts().CPlusPlus20 ? CSK_unspecified : CSK_constexpr);
+ << static_cast<int>(ConstexprKind);
+ NewFD->setConstexprKind(getLangOpts().CPlusPlus20
+ ? ConstexprSpecKind::Unspecified
+ : ConstexprSpecKind::Constexpr);
}
// C++20 [dcl.constexpr]p2: An allocation function, or a
// deallocation function shall not be declared with the consteval
// specifier.
- if (ConstexprKind == CSK_consteval &&
+ if (ConstexprKind == ConstexprSpecKind::Consteval &&
(NewFD->getOverloadedOperator() == OO_New ||
NewFD->getOverloadedOperator() == OO_Array_New ||
NewFD->getOverloadedOperator() == OO_Delete ||
@@ -9094,7 +9169,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
Diag(D.getDeclSpec().getConstexprSpecLoc(),
diag::err_invalid_consteval_decl_kind)
<< NewFD;
- NewFD->setConstexprKind(CSK_constexpr);
+ NewFD->setConstexprKind(ConstexprSpecKind::Constexpr);
}
}
@@ -9125,17 +9200,17 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// If a function is defined as defaulted or deleted, mark it as such now.
// We'll do the relevant checks on defaulted / deleted functions later.
switch (D.getFunctionDefinitionKind()) {
- case FDK_Declaration:
- case FDK_Definition:
- break;
+ case FunctionDefinitionKind::Declaration:
+ case FunctionDefinitionKind::Definition:
+ break;
- case FDK_Defaulted:
- NewFD->setDefaulted();
- break;
+ case FunctionDefinitionKind::Defaulted:
+ NewFD->setDefaulted();
+ break;
- case FDK_Deleted:
- NewFD->setDeletedAsWritten();
- break;
+ case FunctionDefinitionKind::Deleted:
+ NewFD->setDeletedAsWritten();
+ break;
}
if (isa<CXXMethodDecl>(NewFD) && DC == CurContext &&
@@ -9345,6 +9420,9 @@ 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())
@@ -9452,12 +9530,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// that either the specialized function type or the specialized
// template is dependent, and therefore matching will fail. In
// this case, don't check the specialization yet.
- bool InstantiationDependent = false;
if (isFunctionTemplateSpecialization && isFriend &&
(NewFD->getType()->isDependentType() || DC->isDependentContext() ||
- TemplateSpecializationType::anyDependentTemplateArguments(
- TemplateArgs,
- InstantiationDependent))) {
+ TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
+ TemplateArgs.arguments()))) {
assert(HasExplicitTemplateArgs &&
"friend function specialization without template args");
if (CheckDependentFunctionTemplateSpecialization(NewFD, TemplateArgs,
@@ -9642,7 +9718,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID));
} else {
ASTContext::GetBuiltinTypeError Error;
- LookupPredefedObjCSuperType(*this, S, NewFD->getIdentifier());
+ LookupNecessaryTypesForBuiltin(S, BuiltinID);
QualType BuiltinType = Context.GetBuiltinType(BuiltinID, Error);
if (!Error && !BuiltinType.isNull() &&
@@ -9836,17 +9912,17 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// because Sema::ActOnStartOfFunctionDef has not been called yet.
if (const auto *NBA = NewFD->getAttr<NoBuiltinAttr>())
switch (D.getFunctionDefinitionKind()) {
- case FDK_Defaulted:
- case FDK_Deleted:
+ case FunctionDefinitionKind::Defaulted:
+ case FunctionDefinitionKind::Deleted:
Diag(NBA->getLocation(),
diag::err_attribute_no_builtin_on_defaulted_deleted_function)
<< NBA->getSpelling();
break;
- case FDK_Declaration:
+ case FunctionDefinitionKind::Declaration:
Diag(NBA->getLocation(), diag::err_attribute_no_builtin_on_non_definition)
<< NBA->getSpelling();
break;
- case FDK_Definition:
+ case FunctionDefinitionKind::Definition:
break;
}
@@ -10019,31 +10095,50 @@ static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) {
// multiversion functions.
static bool AttrCompatibleWithMultiVersion(attr::Kind Kind,
MultiVersionKind MVType) {
+ // Note: this list/diagnosis must match the list in
+ // checkMultiversionAttributesAllSame.
switch (Kind) {
default:
return false;
case attr::Used:
return MVType == MultiVersionKind::Target;
+ case attr::NonNull:
+ case attr::NoThrow:
+ return true;
}
}
-static bool HasNonMultiVersionAttributes(const FunctionDecl *FD,
- MultiVersionKind MVType) {
+static bool checkNonMultiVersionCompatAttributes(Sema &S,
+ const FunctionDecl *FD,
+ const FunctionDecl *CausedFD,
+ MultiVersionKind MVType) {
+ bool IsCPUSpecificCPUDispatchMVType =
+ MVType == MultiVersionKind::CPUDispatch ||
+ MVType == MultiVersionKind::CPUSpecific;
+ const auto Diagnose = [FD, CausedFD, IsCPUSpecificCPUDispatchMVType](
+ Sema &S, const Attr *A) {
+ S.Diag(FD->getLocation(), diag::err_multiversion_disallowed_other_attr)
+ << IsCPUSpecificCPUDispatchMVType << A;
+ if (CausedFD)
+ S.Diag(CausedFD->getLocation(), diag::note_multiversioning_caused_here);
+ return true;
+ };
+
for (const Attr *A : FD->attrs()) {
switch (A->getKind()) {
case attr::CPUDispatch:
case attr::CPUSpecific:
if (MVType != MultiVersionKind::CPUDispatch &&
MVType != MultiVersionKind::CPUSpecific)
- return true;
+ return Diagnose(S, A);
break;
case attr::Target:
if (MVType != MultiVersionKind::Target)
- return true;
+ return Diagnose(S, A);
break;
default:
if (!AttrCompatibleWithMultiVersion(A->getKind(), MVType))
- return true;
+ return Diagnose(S, A);
break;
}
}
@@ -10177,18 +10272,12 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
MVType == MultiVersionKind::CPUDispatch ||
MVType == MultiVersionKind::CPUSpecific;
- // For now, disallow all other attributes. These should be opt-in, but
- // an analysis of all of them is a future FIXME.
- if (CausesMV && OldFD && HasNonMultiVersionAttributes(OldFD, MVType)) {
- S.Diag(OldFD->getLocation(), diag::err_multiversion_no_other_attrs)
- << IsCPUSpecificCPUDispatchMVType;
- S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
+ if (CausesMV && OldFD &&
+ checkNonMultiVersionCompatAttributes(S, OldFD, NewFD, MVType))
return true;
- }
- if (HasNonMultiVersionAttributes(NewFD, MVType))
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs)
- << IsCPUSpecificCPUDispatchMVType;
+ if (checkNonMultiVersionCompatAttributes(S, NewFD, nullptr, MVType))
+ return true;
// Only allow transition to MultiVersion if it hasn't been used.
if (OldFD && CausesMV && OldFD->isUsed(false))
@@ -10641,6 +10730,12 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
MergeTypeWithPrevious, Previous))
return Redeclaration;
+ // PPC MMA non-pointer types are not allowed as function return types.
+ if (Context.getTargetInfo().getTriple().isPPC64() &&
+ CheckPPCMMAType(NewFD->getReturnType(), NewFD->getLocation())) {
+ NewFD->setInvalidDecl();
+ }
+
// C++11 [dcl.constexpr]p8:
// A constexpr specifier for a non-static member function that is not
// a constructor declares that member function to be const.
@@ -10703,7 +10798,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
NewTemplateDecl->mergePrevDecl(OldTemplateDecl);
NewFD->setPreviousDeclaration(OldFD);
- adjustDeclContextForDeclaratorDecl(NewFD, OldFD);
if (NewFD->isCXXClassMember()) {
NewFD->setAccess(OldTemplateDecl->getAccess());
NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
@@ -10730,7 +10824,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
auto *OldFD = cast<FunctionDecl>(OldDecl);
// This needs to happen first so that 'inline' propagates.
NewFD->setPreviousDeclaration(OldFD);
- adjustDeclContextForDeclaratorDecl(NewFD, OldFD);
if (NewFD->isCXXClassMember())
NewFD->setAccess(OldFD->getAccess());
}
@@ -10760,6 +10853,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
}
}
+ if (LangOpts.OpenMP)
+ ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(NewFD);
+
// Semantic checking for this function declaration (in isolation).
if (getLangOpts().CPlusPlus) {
@@ -10838,7 +10934,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// declaration against the expected type for the builtin.
if (unsigned BuiltinID = NewFD->getBuiltinID()) {
ASTContext::GetBuiltinTypeError Error;
- LookupPredefedObjCSuperType(*this, S, NewFD->getIdentifier());
+ LookupNecessaryTypesForBuiltin(S, BuiltinID);
QualType T = Context.GetBuiltinType(BuiltinID, Error);
// If the type of the builtin differs only in its exception
// specification, that's OK.
@@ -10934,7 +11030,7 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_main)
<< FD->isConsteval()
<< FixItHint::CreateRemoval(DS.getConstexprSpecLoc());
- FD->setConstexprKind(CSK_unspecified);
+ FD->setConstexprKind(ConstexprSpecKind::Unspecified);
}
if (getLangOpts().OpenCL) {
@@ -11090,8 +11186,14 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
// except that the aforementioned are allowed in unevaluated
// expressions. Everything else falls under the
// "may accept other forms of constant expressions" exception.
- // (We never end up here for C++, so the constant expression
- // rules there don't matter.)
+ //
+ // Regular C++ code will not end up here (exceptions: language extensions,
+ // OpenCL C++ etc), so the constant expression rules there don't matter.
+ if (Init->isValueDependent()) {
+ assert(Init->containsErrors() &&
+ "Dependent code should only occur in error-recovery path.");
+ return true;
+ }
const Expr *Culprit;
if (Init->isConstantInitializer(Context, false, &Culprit))
return false;
@@ -12056,7 +12158,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// Try to correct any TypoExprs in the initialization arguments.
for (size_t Idx = 0; Idx < Args.size(); ++Idx) {
ExprResult Res = CorrectDelayedTyposInExpr(
- Args[Idx], VDecl, /*RecoverUncorrectedTypos=*/false,
+ Args[Idx], VDecl, /*RecoverUncorrectedTypos=*/true,
[this, Entity, Kind](Expr *E) {
InitializationSequence Init(*this, Entity, Kind, MultiExprArg(E));
return Init.Failed() ? ExprError() : E;
@@ -12425,7 +12527,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
Diag(Var->getLocation(),
diag::err_constexpr_static_mem_var_requires_init)
- << Var->getDeclName();
+ << Var;
Var->setInvalidDecl();
return;
}
@@ -12447,6 +12549,17 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
}
if (!Var->isInvalidDecl() && RealDecl->hasAttr<LoaderUninitializedAttr>()) {
+ if (Var->getStorageClass() == SC_Extern) {
+ Diag(Var->getLocation(), diag::err_loader_uninitialized_extern_decl)
+ << Var;
+ Var->setInvalidDecl();
+ return;
+ }
+ if (RequireCompleteType(Var->getLocation(), Var->getType(),
+ diag::err_typecheck_decl_incomplete_type)) {
+ Var->setInvalidDecl();
+ return;
+ }
if (CXXRecordDecl *RD = Var->getType()->getAsCXXRecordDecl()) {
if (!RD->hasTrivialDefaultConstructor()) {
Diag(Var->getLocation(), diag::err_loader_uninitialized_trivial_ctor);
@@ -12454,12 +12567,6 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
return;
}
}
- if (Var->getStorageClass() == SC_Extern) {
- Diag(Var->getLocation(), diag::err_loader_uninitialized_extern_decl)
- << Var;
- Var->setInvalidDecl();
- return;
- }
}
VarDecl::DefinitionKind DefKind = Var->isThisDeclarationADefinition();
@@ -12558,8 +12665,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
// definitions with reference type.
if (Type->isReferenceType()) {
Diag(Var->getLocation(), diag::err_reference_var_requires_init)
- << Var->getDeclName()
- << SourceRange(Var->getLocation(), Var->getLocation());
+ << Var << SourceRange(Var->getLocation(), Var->getLocation());
Var->setInvalidDecl();
return;
}
@@ -12690,9 +12796,21 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) {
Error = 4;
break;
}
+
+ // for-range-declaration cannot be given a storage class specifier con't.
+ switch (VD->getTSCSpec()) {
+ case TSCS_thread_local:
+ Error = 6;
+ break;
+ case TSCS___thread:
+ case TSCS__Thread_local:
+ case TSCS_unspecified:
+ break;
+ }
+
if (Error != -1) {
Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class)
- << VD->getDeclName() << Error;
+ << VD << Error;
D->setInvalidDecl();
}
}
@@ -12714,7 +12832,7 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
DS.SetTypeSpecType(DeclSpec::TST_auto, IdentLoc, PrevSpec, DiagID,
getPrintingPolicy());
- Declarator D(DS, DeclaratorContext::ForContext);
+ Declarator D(DS, DeclaratorContext::ForInit);
D.SetIdentifier(Ident, IdentLoc);
D.takeAttributes(Attrs, AttrEnd);
@@ -12858,20 +12976,64 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
AttributeCommonInfo::AS_Pragma));
}
+ if (!var->getType()->isStructureType() && var->hasInit() &&
+ isa<InitListExpr>(var->getInit())) {
+ const auto *ILE = cast<InitListExpr>(var->getInit());
+ unsigned NumInits = ILE->getNumInits();
+ if (NumInits > 2)
+ for (unsigned I = 0; I < NumInits; ++I) {
+ const auto *Init = ILE->getInit(I);
+ if (!Init)
+ break;
+ const auto *SL = dyn_cast<StringLiteral>(Init->IgnoreImpCasts());
+ if (!SL)
+ break;
+
+ unsigned NumConcat = SL->getNumConcatenated();
+ // Diagnose missing comma in string array initialization.
+ // Do not warn when all the elements in the initializer are concatenated
+ // together. Do not warn for macros too.
+ if (NumConcat == 2 && !SL->getBeginLoc().isMacroID()) {
+ bool OnlyOneMissingComma = true;
+ for (unsigned J = I + 1; J < NumInits; ++J) {
+ const auto *Init = ILE->getInit(J);
+ if (!Init)
+ break;
+ const auto *SLJ = dyn_cast<StringLiteral>(Init->IgnoreImpCasts());
+ if (!SLJ || SLJ->getNumConcatenated() > 1) {
+ OnlyOneMissingComma = false;
+ break;
+ }
+ }
+
+ if (OnlyOneMissingComma) {
+ SmallVector<FixItHint, 1> Hints;
+ for (unsigned i = 0; i < NumConcat - 1; ++i)
+ Hints.push_back(FixItHint::CreateInsertion(
+ PP.getLocForEndOfToken(SL->getStrTokenLoc(i)), ","));
+
+ Diag(SL->getStrTokenLoc(1),
+ diag::warn_concatenated_literal_array_init)
+ << Hints;
+ Diag(SL->getBeginLoc(),
+ diag::note_concatenated_string_literal_silence);
+ }
+ // In any case, stop now.
+ break;
+ }
+ }
+ }
+
// All the following checks are C++ only.
if (!getLangOpts().CPlusPlus) {
- // If this variable must be emitted, add it as an initializer for the
- // current module.
- if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty())
- Context.addModuleInitializer(ModuleScopes.back().Module, var);
- return;
+ // If this variable must be emitted, add it as an initializer for the
+ // current module.
+ if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty())
+ Context.addModuleInitializer(ModuleScopes.back().Module, var);
+ return;
}
- if (auto *DD = dyn_cast<DecompositionDecl>(var))
- CheckCompleteDecompositionDeclaration(DD);
-
QualType type = var->getType();
- if (type->isDependentType()) return;
if (var->hasAttr<BlocksAttr>())
getCurFunction()->addByrefBlockVar(var);
@@ -12880,79 +13042,93 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
bool IsGlobal = GlobalStorage && !var->isStaticLocal();
QualType baseType = Context.getBaseElementType(type);
- if (Init && !Init->isValueDependent()) {
- if (var->isConstexpr()) {
- SmallVector<PartialDiagnosticAt, 8> Notes;
- if (!var->evaluateValue(Notes) || !var->isInitICE()) {
- SourceLocation DiagLoc = var->getLocation();
- // If the note doesn't add any useful information other than a source
- // location, fold it into the primary diagnostic.
- if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
- diag::note_invalid_subexpr_in_const_expr) {
- DiagLoc = Notes[0].first;
- Notes.clear();
- }
- Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
- << var << Init->getSourceRange();
- for (unsigned I = 0, N = Notes.size(); I != N; ++I)
- Diag(Notes[I].first, Notes[I].second);
+ // Check whether the initializer is sufficiently constant.
+ if (!type->isDependentType() && Init && !Init->isValueDependent() &&
+ (GlobalStorage || var->isConstexpr() ||
+ var->mightBeUsableInConstantExpressions(Context))) {
+ // If this variable might have a constant initializer or might be usable in
+ // constant expressions, check whether or not it actually is now. We can't
+ // do this lazily, because the result might depend on things that change
+ // later, such as which constexpr functions happen to be defined.
+ SmallVector<PartialDiagnosticAt, 8> Notes;
+ bool HasConstInit;
+ if (!getLangOpts().CPlusPlus11) {
+ // Prior to C++11, in contexts where a constant initializer is required,
+ // the set of valid constant initializers is described by syntactic rules
+ // in [expr.const]p2-6.
+ // FIXME: Stricter checking for these rules would be useful for constinit /
+ // -Wglobal-constructors.
+ HasConstInit = checkConstInit();
+
+ // Compute and cache the constant value, and remember that we have a
+ // constant initializer.
+ if (HasConstInit) {
+ (void)var->checkForConstantInitialization(Notes);
+ Notes.clear();
+ } else if (CacheCulprit) {
+ Notes.emplace_back(CacheCulprit->getExprLoc(),
+ PDiag(diag::note_invalid_subexpr_in_const_expr));
+ Notes.back().second << CacheCulprit->getSourceRange();
}
- } else if (var->mightBeUsableInConstantExpressions(Context)) {
- // Check whether the initializer of a const variable of integral or
- // enumeration type is an ICE now, since we can't tell whether it was
- // initialized by a constant expression if we check later.
- var->checkInitIsICE();
- }
-
- // Don't emit further diagnostics about constexpr globals since they
- // were just diagnosed.
- if (!var->isConstexpr() && GlobalStorage && var->hasAttr<ConstInitAttr>()) {
- // FIXME: Need strict checking in C++03 here.
- bool DiagErr = getLangOpts().CPlusPlus11
- ? !var->checkInitIsICE() : !checkConstInit();
- if (DiagErr) {
- auto *Attr = var->getAttr<ConstInitAttr>();
- Diag(var->getLocation(), diag::err_require_constant_init_failed)
- << Init->getSourceRange();
- Diag(Attr->getLocation(),
- diag::note_declared_required_constant_init_here)
- << Attr->getRange() << Attr->isConstinit();
- if (getLangOpts().CPlusPlus11) {
- APValue Value;
- SmallVector<PartialDiagnosticAt, 8> Notes;
- Init->EvaluateAsInitializer(Value, getASTContext(), var, Notes);
- for (auto &it : Notes)
- Diag(it.first, it.second);
- } else {
- Diag(CacheCulprit->getExprLoc(),
- diag::note_invalid_subexpr_in_const_expr)
- << CacheCulprit->getSourceRange();
- }
+ } else {
+ // Evaluate the initializer to see if it's a constant initializer.
+ HasConstInit = var->checkForConstantInitialization(Notes);
+ }
+
+ if (HasConstInit) {
+ // FIXME: Consider replacing the initializer with a ConstantExpr.
+ } else if (var->isConstexpr()) {
+ SourceLocation DiagLoc = var->getLocation();
+ // If the note doesn't add any useful information other than a source
+ // location, fold it into the primary diagnostic.
+ if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
+ diag::note_invalid_subexpr_in_const_expr) {
+ DiagLoc = Notes[0].first;
+ Notes.clear();
}
- }
- else if (!var->isConstexpr() && IsGlobal &&
- !getDiagnostics().isIgnored(diag::warn_global_constructor,
- var->getLocation())) {
+ Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
+ << var << Init->getSourceRange();
+ for (unsigned I = 0, N = Notes.size(); I != N; ++I)
+ Diag(Notes[I].first, Notes[I].second);
+ } else if (GlobalStorage && var->hasAttr<ConstInitAttr>()) {
+ auto *Attr = var->getAttr<ConstInitAttr>();
+ Diag(var->getLocation(), diag::err_require_constant_init_failed)
+ << Init->getSourceRange();
+ Diag(Attr->getLocation(), diag::note_declared_required_constant_init_here)
+ << Attr->getRange() << Attr->isConstinit();
+ for (auto &it : Notes)
+ Diag(it.first, it.second);
+ } else if (IsGlobal &&
+ !getDiagnostics().isIgnored(diag::warn_global_constructor,
+ var->getLocation())) {
// Warn about globals which don't have a constant initializer. Don't
// warn about globals with a non-trivial destructor because we already
// warned about them.
CXXRecordDecl *RD = baseType->getAsCXXRecordDecl();
if (!(RD && !RD->hasTrivialDestructor())) {
+ // checkConstInit() here permits trivial default initialization even in
+ // C++11 onwards, where such an initializer is not a constant initializer
+ // but nonetheless doesn't require a global constructor.
if (!checkConstInit())
Diag(var->getLocation(), diag::warn_global_constructor)
- << Init->getSourceRange();
+ << Init->getSourceRange();
}
}
}
// Require the destructor.
- if (const RecordType *recordType = baseType->getAs<RecordType>())
- FinalizeVarWithDestructor(var, recordType);
+ if (!type->isDependentType())
+ if (const RecordType *recordType = baseType->getAs<RecordType>())
+ FinalizeVarWithDestructor(var, recordType);
// If this variable must be emitted, add it as an initializer for the current
// module.
if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty())
Context.addModuleInitializer(ModuleScopes.back().Module, var);
+
+ // Build the bindings if this is a structured binding declaration.
+ if (auto *DD = dyn_cast<DecompositionDecl>(var))
+ CheckCompleteDecompositionDeclaration(DD);
}
/// Determines if a variable's alignment is dependent.
@@ -13064,32 +13240,9 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
}
}
- if (VD->isStaticLocal()) {
+ if (VD->isStaticLocal())
CheckStaticLocalForDllExport(VD);
- if (dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod())) {
- // CUDA 8.0 E.3.9.4: Within the body of a __device__ or __global__
- // function, only __shared__ variables or variables without any device
- // memory qualifiers may be declared with static storage class.
- // Note: It is unclear how a function-scope non-const static variable
- // without device memory qualifier is implemented, therefore only static
- // const variable without device memory qualifier is allowed.
- [&]() {
- if (!getLangOpts().CUDA)
- return;
- if (VD->hasAttr<CUDASharedAttr>())
- return;
- if (VD->getType().isConstQualified() &&
- !(VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>()))
- return;
- if (CUDADiagIfDeviceCode(VD->getLocation(),
- diag::err_device_static_local_var)
- << CurrentCUDATarget())
- VD->setInvalidDecl();
- }();
- }
- }
-
// Perform check for initializers of device-side global variables.
// CUDA allows empty constructors as initializers (see E.2.3.1, CUDA
// 7.5). We must also apply the same checks to all __shared__
@@ -13167,20 +13320,20 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
if (!MagicValueExpr) {
continue;
}
- llvm::APSInt MagicValueInt;
- if (!MagicValueExpr->isIntegerConstantExpr(MagicValueInt, Context)) {
+ Optional<llvm::APSInt> MagicValueInt;
+ if (!(MagicValueInt = MagicValueExpr->getIntegerConstantExpr(Context))) {
Diag(I->getRange().getBegin(),
diag::err_type_tag_for_datatype_not_ice)
<< LangOpts.CPlusPlus << MagicValueExpr->getSourceRange();
continue;
}
- if (MagicValueInt.getActiveBits() > 64) {
+ if (MagicValueInt->getActiveBits() > 64) {
Diag(I->getRange().getBegin(),
diag::err_type_tag_for_datatype_too_large)
<< LangOpts.CPlusPlus << MagicValueExpr->getSourceRange();
continue;
}
- uint64_t MagicValue = MagicValueInt.getZExtValue();
+ uint64_t MagicValue = MagicValueInt->getZExtValue();
RegisterTypeTagForDatatype(I->getArgumentKind(),
MagicValue,
I->getMatchingCType(),
@@ -13415,7 +13568,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
<< getLangOpts().CPlusPlus17;
if (DS.hasConstexprSpecifier())
Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr)
- << 0 << D.getDeclSpec().getConstexprSpecifier();
+ << 0 << static_cast<int>(D.getDeclSpec().getConstexprSpecifier());
DiagnoseFunctionSpecifiers(DS);
@@ -13473,9 +13626,8 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
if (D.getDeclSpec().isModulePrivateSpecified())
Diag(New->getLocation(), diag::err_module_private_local)
- << 1 << New->getDeclName()
- << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
- << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
+ << 1 << New << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
+ << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
if (New->hasAttr<BlocksAttr>()) {
Diag(New->getLocation(), diag::err_block_on_nonlocal);
@@ -13527,8 +13679,7 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(
if (!ReturnTy->isDependentType() && ReturnTy.isPODType(Context)) {
unsigned Size = Context.getTypeSizeInChars(ReturnTy).getQuantity();
if (Size > LangOpts.NumLargeByValueCopy)
- Diag(D->getLocation(), diag::warn_return_value_size)
- << D->getDeclName() << Size;
+ Diag(D->getLocation(), diag::warn_return_value_size) << D << Size;
}
// Warn if any parameter is pass-by-value and larger than the specified
@@ -13540,7 +13691,7 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(
unsigned Size = Context.getTypeSizeInChars(T).getQuantity();
if (Size > LangOpts.NumLargeByValueCopy)
Diag(Parameter->getLocation(), diag::warn_parameter_size)
- << Parameter->getDeclName() << Size;
+ << Parameter << Size;
}
}
@@ -13624,6 +13775,12 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
New->setInvalidDecl();
}
+ // PPC MMA non-pointer types are not allowed as function argument types.
+ if (Context.getTargetInfo().getTriple().isPPC64() &&
+ CheckPPCMMAType(New->getOriginalType(), New->getLocation())) {
+ New->setInvalidDecl();
+ }
+
return New;
}
@@ -13655,7 +13812,7 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
// Use the identifier location for the type source range.
DS.SetRangeStart(FTI.Params[i].IdentLoc);
DS.SetRangeEnd(FTI.Params[i].IdentLoc);
- Declarator ParamD(DS, DeclaratorContext::KNRTypeListContext);
+ Declarator ParamD(DS, DeclaratorContext::KNRTypeList);
ParamD.SetIdentifier(FTI.Params[i].Ident, FTI.Params[i].IdentLoc);
FTI.Params[i].Param = ActOnParamDeclarator(S, ParamD);
}
@@ -13678,19 +13835,17 @@ Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D,
// variant` annotation which specifies the mangled definition as a
// specialization function under the OpenMP context defined as part of the
// `omp begin declare variant`.
- FunctionDecl *BaseFD = nullptr;
- if (LangOpts.OpenMP && isInOpenMPDeclareVariantScope() &&
- TemplateParameterLists.empty())
- BaseFD = ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
- ParentScope, D);
+ SmallVector<FunctionDecl *, 4> Bases;
+ if (LangOpts.OpenMP && isInOpenMPDeclareVariantScope())
+ ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
+ ParentScope, D, TemplateParameterLists, Bases);
- D.setFunctionDefinitionKind(FDK_Definition);
+ D.setFunctionDefinitionKind(FunctionDefinitionKind::Definition);
Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists);
Decl *Dcl = ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody);
- if (BaseFD)
- ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
- cast<FunctionDecl>(Dcl), BaseFD);
+ if (!Bases.empty())
+ ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Dcl, Bases);
return Dcl;
}
@@ -13759,69 +13914,23 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
const FunctionDecl *EffectiveDefinition,
SkipBodyInfo *SkipBody) {
const FunctionDecl *Definition = EffectiveDefinition;
- if (!Definition && !FD->isDefined(Definition) && !FD->isCXXClassMember()) {
- // If this is a friend function defined in a class template, it does not
- // have a body until it is used, nevertheless it is a definition, see
- // [temp.inst]p2:
- //
- // ... for the purpose of determining whether an instantiated redeclaration
- // is valid according to [basic.def.odr] and [class.mem], a declaration that
- // corresponds to a definition in the template is considered to be a
- // definition.
- //
- // The following code must produce redefinition error:
- //
- // template<typename T> struct C20 { friend void func_20() {} };
- // C20<int> c20i;
- // void func_20() {}
- //
- for (auto I : FD->redecls()) {
- if (I != FD && !I->isInvalidDecl() &&
- I->getFriendObjectKind() != Decl::FOK_None) {
- if (FunctionDecl *Original = I->getInstantiatedFromMemberFunction()) {
- if (FunctionDecl *OrigFD = FD->getInstantiatedFromMemberFunction()) {
- // A merged copy of the same function, instantiated as a member of
- // the same class, is OK.
- if (declaresSameEntity(OrigFD, Original) &&
- declaresSameEntity(cast<Decl>(I->getLexicalDeclContext()),
- cast<Decl>(FD->getLexicalDeclContext())))
- continue;
- }
+ if (!Definition &&
+ !FD->isDefined(Definition, /*CheckForPendingFriendDefinition*/ true))
+ return;
- if (Original->isThisDeclarationADefinition()) {
- Definition = I;
- break;
- }
- }
+ if (Definition->getFriendObjectKind() != Decl::FOK_None) {
+ if (FunctionDecl *OrigDef = Definition->getInstantiatedFromMemberFunction()) {
+ if (FunctionDecl *OrigFD = FD->getInstantiatedFromMemberFunction()) {
+ // A merged copy of the same function, instantiated as a member of
+ // the same class, is OK.
+ if (declaresSameEntity(OrigFD, OrigDef) &&
+ declaresSameEntity(cast<Decl>(Definition->getLexicalDeclContext()),
+ cast<Decl>(FD->getLexicalDeclContext())))
+ return;
}
}
}
- if (!Definition)
- // Similar to friend functions a friend function template may be a
- // definition and do not have a body if it is instantiated in a class
- // template.
- if (FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate()) {
- for (auto I : FTD->redecls()) {
- auto D = cast<FunctionTemplateDecl>(I);
- if (D != FTD) {
- assert(!D->isThisDeclarationADefinition() &&
- "More than one definition in redeclaration chain");
- if (D->getFriendObjectKind() != Decl::FOK_None)
- if (FunctionTemplateDecl *FT =
- D->getInstantiatedFromMemberTemplate()) {
- if (FT->isThisDeclarationADefinition()) {
- Definition = D->getTemplatedDecl();
- break;
- }
- }
- }
- }
- }
-
- if (!Definition)
- return;
-
if (canRedefineFunction(Definition, getLangOpts()))
return;
@@ -13848,9 +13957,9 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
if (getLangOpts().GNUMode && Definition->isInlineSpecified() &&
Definition->getStorageClass() == SC_Extern)
Diag(FD->getLocation(), diag::err_redefinition_extern_inline)
- << FD->getDeclName() << getLangOpts().CPlusPlus;
+ << FD << getLangOpts().CPlusPlus;
else
- Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName();
+ Diag(FD->getLocation(), diag::err_redefinition) << FD;
Diag(Definition->getLocation(), diag::note_previous_definition);
FD->setInvalidDecl();
@@ -13939,9 +14048,20 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
FD->setInvalidDecl();
}
- // See if this is a redefinition. If 'will have body' is already set, then
- // these checks were already performed when it was set.
- if (!FD->willHaveBody() && !FD->isLateTemplateParsed()) {
+ if (auto *Ctor = dyn_cast<CXXConstructorDecl>(FD)) {
+ if (Ctor->getTemplateSpecializationKind() == TSK_ExplicitSpecialization &&
+ Ctor->isDefaultConstructor() &&
+ Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ // If this is an MS ABI dllexport default constructor, instantiate any
+ // default arguments.
+ InstantiateDefaultCtorDefaultArgs(Ctor);
+ }
+ }
+
+ // See if this is a redefinition. If 'will have body' (or similar) is already
+ // set, then these checks were already performed when it was set.
+ if (!FD->willHaveBody() && !FD->isLateTemplateParsed() &&
+ !FD->isThisDeclarationInstantiatedFromAFriendDefinition()) {
CheckForFunctionRedefinition(FD, nullptr, SkipBody);
// If we're skipping the body, we're done. Don't enter the scope.
@@ -14181,12 +14301,16 @@ static void diagnoseImplicitlyRetainedSelf(Sema &S) {
Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
bool IsInstantiation) {
+ FunctionScopeInfo *FSI = getCurFunction();
FunctionDecl *FD = dcl ? dcl->getAsFunction() : nullptr;
+ if (FSI->UsesFPIntrin && !FD->hasAttr<StrictFPAttr>())
+ FD->addAttr(StrictFPAttr::CreateImplicit(Context));
+
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr;
- if (getLangOpts().Coroutines && getCurFunction()->isCoroutine())
+ if (getLangOpts().Coroutines && FSI->isCoroutine())
CheckCompletedCoroutineBody(FD, Body);
// Do not call PopExpressionEvaluationContext() if it is a lambda because one
@@ -14263,7 +14387,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
// to deduce an implicit return type.
if (FD->getReturnType()->isRecordType() &&
(!getLangOpts().CPlusPlus || !FD->isDependentContext()))
- computeNRVO(Body, getCurFunction());
+ computeNRVO(Body, FSI);
}
// GNU warning -Wmissing-prototypes:
@@ -14387,14 +14511,14 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
MD->getReturnType(), MD);
if (Body)
- computeNRVO(Body, getCurFunction());
+ computeNRVO(Body, FSI);
}
- if (getCurFunction()->ObjCShouldCallSuper) {
+ if (FSI->ObjCShouldCallSuper) {
Diag(MD->getEndLoc(), diag::warn_objc_missing_super_call)
<< MD->getSelector().getAsString();
- getCurFunction()->ObjCShouldCallSuper = false;
+ FSI->ObjCShouldCallSuper = false;
}
- if (getCurFunction()->ObjCWarnForNoDesignatedInitChain) {
+ if (FSI->ObjCWarnForNoDesignatedInitChain) {
const ObjCMethodDecl *InitMethod = nullptr;
bool isDesignated =
MD->isDesignatedInitializerForTheInterface(&InitMethod);
@@ -14419,14 +14543,14 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
Diag(InitMethod->getLocation(),
diag::note_objc_designated_init_marked_here);
}
- getCurFunction()->ObjCWarnForNoDesignatedInitChain = false;
+ FSI->ObjCWarnForNoDesignatedInitChain = false;
}
- if (getCurFunction()->ObjCWarnForNoInitDelegation) {
+ 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);
- getCurFunction()->ObjCWarnForNoInitDelegation = false;
+ FSI->ObjCWarnForNoInitDelegation = false;
}
diagnoseImplicitlyRetainedSelf(*this);
@@ -14437,10 +14561,10 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
return nullptr;
}
- if (Body && getCurFunction()->HasPotentialAvailabilityViolations)
+ if (Body && FSI->HasPotentialAvailabilityViolations)
DiagnoseUnguardedAvailabilityViolations(dcl);
- assert(!getCurFunction()->ObjCShouldCallSuper &&
+ assert(!FSI->ObjCShouldCallSuper &&
"This should only be set for ObjC methods, which should have been "
"handled in the block above.");
@@ -14453,7 +14577,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body));
// Verify that gotos and switch cases don't jump into scopes illegally.
- if (getCurFunction()->NeedsScopeChecking() &&
+ if (FSI->NeedsScopeChecking() &&
!PP.isCodeCompletionEnabled())
DiagnoseInvalidJumps(Body);
@@ -14468,11 +14592,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
// 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 (getDiagnostics().hasUncompilableErrorOccurred() ||
+ if (hasUncompilableErrorOccurred() ||
getDiagnostics().getSuppressAllDiagnostics()) {
DiscardCleanupsInEvaluationContext();
}
- if (!getDiagnostics().hasUncompilableErrorOccurred() &&
+ if (!hasUncompilableErrorOccurred() &&
!isa<FunctionTemplateDecl>(dcl)) {
// Since the body is valid, issue any analysis-based warnings that are
// enabled.
@@ -14524,11 +14648,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
// 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 (getDiagnostics().hasUncompilableErrorOccurred()) {
+ if (hasUncompilableErrorOccurred()) {
DiscardCleanupsInEvaluationContext();
}
- if (LangOpts.OpenMP || LangOpts.CUDA || LangOpts.SYCLIsDevice) {
+ if (FD && (LangOpts.OpenMP || LangOpts.CUDA || LangOpts.SYCLIsDevice)) {
auto ES = getEmissionStatus(FD);
if (ES == Sema::FunctionEmissionStatus::Emitted ||
ES == Sema::FunctionEmissionStatus::Unknown)
@@ -14635,7 +14759,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
(void)Error; // Silence warning.
assert(!Error && "Error setting up implicit decl!");
SourceLocation NoLoc;
- Declarator D(DS, DeclaratorContext::BlockContext);
+ Declarator D(DS, DeclaratorContext::Block);
D.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/false,
/*IsAmbiguous=*/false,
/*LParenLoc=*/NoLoc,
@@ -14905,9 +15029,10 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
if (D.getDeclSpec().isModulePrivateSpecified()) {
if (CurContext->isFunctionOrMethod())
Diag(NewTD->getLocation(), diag::err_module_private_local)
- << 2 << NewTD->getDeclName()
- << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
- << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
+ << 2 << NewTD
+ << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
+ << FixItHint::CreateRemoval(
+ D.getDeclSpec().getModulePrivateSpecLoc());
else
NewTD->setModulePrivate();
}
@@ -15295,6 +15420,10 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
isMemberSpecialization = true;
}
}
+
+ if (!TemplateParameterLists.empty() && isMemberSpecialization &&
+ CheckTemplateDeclScope(S, TemplateParameterLists.back()))
+ return nullptr;
}
// Figure out the underlying type if this a enum declaration. We need to do
@@ -15615,6 +15744,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// type declared by an elaborated-type-specifier. In C that is not correct
// and we should instead merge compatible types found by lookup.
if (getLangOpts().CPlusPlus) {
+ // FIXME: This can perform qualified lookups into function contexts,
+ // which are meaningless.
Previous.setRedeclarationKind(forRedeclarationInCurContext());
LookupQualifiedName(Previous, SearchDC);
} else {
@@ -16332,7 +16463,7 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
return BitWidth;
llvm::APSInt Value;
- ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Value);
+ ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Value, AllowFold);
if (ICE.isInvalid())
return ICE;
BitWidth = ICE.get();
@@ -16352,6 +16483,13 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
<< Value.toString(10);
}
+ // The size of the bit-field must not exceed our maximum permitted object
+ // size.
+ if (Value.getActiveBits() > ConstantArrayType::getMaxSizeBits(Context)) {
+ return Diag(FieldLoc, diag::err_bitfield_too_wide)
+ << !FieldName << FieldName << Value.toString(10);
+ }
+
if (!FieldTy->isDependentType()) {
uint64_t TypeStorageSize = Context.getTypeSize(FieldTy);
uint64_t TypeWidth = Context.getIntWidth(FieldTy);
@@ -16369,25 +16507,21 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
CStdConstraintViolation ? TypeWidth : TypeStorageSize;
if (FieldName)
return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_width)
- << FieldName << (unsigned)Value.getZExtValue()
+ << FieldName << Value.toString(10)
<< !CStdConstraintViolation << DiagWidth;
return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_width)
- << (unsigned)Value.getZExtValue() << !CStdConstraintViolation
+ << Value.toString(10) << !CStdConstraintViolation
<< DiagWidth;
}
// Warn on types where the user might conceivably expect to get all
// specified bits as value bits: that's all integral types other than
// 'bool'.
- if (BitfieldIsOverwide && !FieldTy->isBooleanType()) {
- if (FieldName)
- Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_width)
- << FieldName << (unsigned)Value.getZExtValue()
- << (unsigned)TypeWidth;
- else
- Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_width)
- << (unsigned)Value.getZExtValue() << (unsigned)TypeWidth;
+ if (BitfieldIsOverwide && !FieldTy->isBooleanType() && FieldName) {
+ Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_width)
+ << FieldName << Value.toString(10)
+ << (unsigned)TypeWidth;
}
}
@@ -16581,27 +16715,9 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
if (!InvalidDecl && T->isVariablyModifiedType()) {
- bool SizeIsNegative;
- llvm::APSInt Oversized;
-
- TypeSourceInfo *FixedTInfo =
- TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context,
- SizeIsNegative,
- Oversized);
- if (FixedTInfo) {
- Diag(Loc, diag::warn_illegal_constant_array_size);
- TInfo = FixedTInfo;
- T = FixedTInfo->getType();
- } else {
- if (SizeIsNegative)
- Diag(Loc, diag::err_typecheck_negative_array_size);
- else if (Oversized.getBoolValue())
- Diag(Loc, diag::err_array_too_large)
- << Oversized.toString(10);
- else
- Diag(Loc, diag::err_typecheck_field_variable_size);
+ if (!tryToFixVariablyModifiedVarType(
+ *this, TInfo, T, Loc, diag::err_typecheck_field_variable_size))
InvalidDecl = true;
- }
}
// Fields can not have abstract class types
@@ -16622,14 +16738,6 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
BitWidth = nullptr;
ZeroWidth = false;
}
-
- // Only data members can have in-class initializers.
- if (BitWidth && !II && InitStyle) {
- Diag(Loc, diag::err_anon_bitfield_init);
- InvalidDecl = true;
- BitWidth = nullptr;
- ZeroWidth = false;
- }
}
// Check that 'mutable' is consistent with the type of the declaration.
@@ -16717,6 +16825,11 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
if (T.isObjCGCWeak())
Diag(Loc, diag::warn_attribute_weak_on_field);
+ // PPC MMA non-pointer types are not allowed as field types.
+ if (Context.getTargetInfo().getTriple().isPPC64() &&
+ CheckPPCMMAType(T, NewFD->getLocation()))
+ NewFD->setInvalidDecl();
+
NewFD->setAccess(AS);
return NewFD;
}
@@ -16830,8 +16943,9 @@ Decl *Sema::ActOnIvar(Scope *S,
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
else if (T->isVariablyModifiedType()) {
- Diag(Loc, diag::err_typecheck_ivar_variable_size);
- D.setInvalidType();
+ if (!tryToFixVariablyModifiedVarType(
+ *this, TInfo, T, Loc, diag::err_typecheck_ivar_variable_size))
+ D.setInvalidType();
}
// Get the visibility (access control) for this ivar.
@@ -17294,7 +17408,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record);
CheckForZeroSize =
CXXRecord->getLexicalDeclContext()->isExternCContext() &&
- !CXXRecord->isDependentType() &&
+ !CXXRecord->isDependentType() && !inTemplateInstantiation() &&
CXXRecord->isCLike();
}
if (CheckForZeroSize) {
@@ -17458,6 +17572,8 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
if (Enum->isDependentType() || Val->isTypeDependent())
EltTy = Context.DependentTy;
else {
+ // FIXME: We don't allow folding in C++11 mode for an enum with a fixed
+ // underlying type, but do allow it in all other contexts.
if (getLangOpts().CPlusPlus11 && Enum->isFixed()) {
// C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the
// constant-expression in the enumerator-definition shall be a converted
@@ -17471,8 +17587,9 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
else
Val = Converted.get();
} else if (!Val->isValueDependent() &&
- !(Val = VerifyIntegerConstantExpression(Val,
- &EnumVal).get())) {
+ !(Val =
+ VerifyIntegerConstantExpression(Val, &EnumVal, AllowFold)
+ .get())) {
// C99 6.7.2.2p2: Make sure we have an integer constant expression.
} else {
if (Enum->isComplete()) {
@@ -18093,11 +18210,9 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
// Adjust the Expr initializer and type.
if (ECD->getInitExpr() &&
!Context.hasSameType(NewTy, ECD->getInitExpr()->getType()))
- ECD->setInitExpr(ImplicitCastExpr::Create(Context, NewTy,
- CK_IntegralCast,
- ECD->getInitExpr(),
- /*base paths*/ nullptr,
- VK_RValue));
+ ECD->setInitExpr(ImplicitCastExpr::Create(
+ Context, NewTy, CK_IntegralCast, ECD->getInitExpr(),
+ /*base paths*/ nullptr, VK_RValue, FPOptionsOverride()));
if (getLangOpts().CPlusPlus)
// C++ [dcl.enum]p4: Following the closing brace of an
// enum-specifier, each enumerator has the type of its
@@ -18217,42 +18332,51 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD,
if (FD->isDependentContext())
return FunctionEmissionStatus::TemplateDiscarded;
- FunctionEmissionStatus OMPES = FunctionEmissionStatus::Unknown;
+ // Check whether this function is an externally visible definition.
+ auto IsEmittedForExternalSymbol = [this, FD]() {
+ // We have to check the GVA linkage of the function's *definition* -- if we
+ // only have a declaration, we don't know whether or not the function will
+ // be emitted, because (say) the definition could include "inline".
+ FunctionDecl *Def = FD->getDefinition();
+
+ return Def && !isDiscardableGVALinkage(
+ getASTContext().GetGVALinkageForFunction(Def));
+ };
+
if (LangOpts.OpenMPIsDevice) {
+ // In OpenMP device mode we will not emit host only functions, or functions
+ // we don't need due to their linkage.
Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
OMPDeclareTargetDeclAttr::getDeviceType(FD->getCanonicalDecl());
- if (DevTy.hasValue()) {
+ // DevTy may be changed later by
+ // #pragma omp declare target to(*) device_type(*).
+ // Therefore DevTyhaving no value does not imply host. The emission status
+ // will be checked again at the end of compilation unit with Final = true.
+ if (DevTy.hasValue())
if (*DevTy == OMPDeclareTargetDeclAttr::DT_Host)
- OMPES = FunctionEmissionStatus::OMPDiscarded;
- else if (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost ||
- *DevTy == OMPDeclareTargetDeclAttr::DT_Any) {
- OMPES = FunctionEmissionStatus::Emitted;
- }
- }
- } else if (LangOpts.OpenMP) {
- // In OpenMP 4.5 all the functions are host functions.
- if (LangOpts.OpenMP <= 45) {
- OMPES = FunctionEmissionStatus::Emitted;
- } else {
- Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
- OMPDeclareTargetDeclAttr::getDeviceType(FD->getCanonicalDecl());
- // In OpenMP 5.0 or above, DevTy may be changed later by
- // #pragma omp declare target to(*) device_type(*). Therefore DevTy
- // having no value does not imply host. The emission status will be
- // checked again at the end of compilation unit.
- if (DevTy.hasValue()) {
- if (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
- OMPES = FunctionEmissionStatus::OMPDiscarded;
- } else if (*DevTy == OMPDeclareTargetDeclAttr::DT_Host ||
- *DevTy == OMPDeclareTargetDeclAttr::DT_Any)
- OMPES = FunctionEmissionStatus::Emitted;
- } else if (Final)
- OMPES = FunctionEmissionStatus::Emitted;
- }
- }
- if (OMPES == FunctionEmissionStatus::OMPDiscarded ||
- (OMPES == FunctionEmissionStatus::Emitted && !LangOpts.CUDA))
- return OMPES;
+ return FunctionEmissionStatus::OMPDiscarded;
+ // If we have an explicit value for the device type, or we are in a target
+ // declare context, we need to emit all extern and used symbols.
+ if (isInOpenMPDeclareTargetContext() || DevTy.hasValue())
+ if (IsEmittedForExternalSymbol())
+ return FunctionEmissionStatus::Emitted;
+ // Device mode only emits what it must, if it wasn't tagged yet and needed,
+ // we'll omit it.
+ if (Final)
+ return FunctionEmissionStatus::OMPDiscarded;
+ } else if (LangOpts.OpenMP > 45) {
+ // In OpenMP host compilation prior to 5.0 everything was an emitted host
+ // function. In 5.0, no_host was introduced which might cause a function to
+ // be ommitted.
+ Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
+ OMPDeclareTargetDeclAttr::getDeviceType(FD->getCanonicalDecl());
+ if (DevTy.hasValue())
+ if (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
+ return FunctionEmissionStatus::OMPDiscarded;
+ }
+
+ if (Final && LangOpts.OpenMP && !LangOpts.CUDA)
+ return FunctionEmissionStatus::Emitted;
if (LangOpts.CUDA) {
// When compiling for device, host functions are never emitted. Similarly,
@@ -18266,17 +18390,7 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD,
(T == Sema::CFT_Device || T == Sema::CFT_Global))
return FunctionEmissionStatus::CUDADiscarded;
- // Check whether this function is externally visible -- if so, it's
- // known-emitted.
- //
- // We have to check the GVA linkage of the function's *definition* -- if we
- // only have a declaration, we don't know whether or not the function will
- // be emitted, because (say) the definition could include "inline".
- FunctionDecl *Def = FD->getDefinition();
-
- if (Def &&
- !isDiscardableGVALinkage(getASTContext().GetGVALinkageForFunction(Def))
- && (!LangOpts.OpenMP || OMPES == FunctionEmissionStatus::Emitted))
+ if (IsEmittedForExternalSymbol())
return FunctionEmissionStatus::Emitted;
}