summaryrefslogtreecommitdiff
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.cpp845
1 files changed, 624 insertions, 221 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 507e4a6cd4365..3e2b61ae8cdf6 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/EvaluatedExprVisitor.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/NonTrivialTypeVisitor.h"
#include "clang/AST/StmtCXX.h"
@@ -47,6 +48,7 @@
#include <algorithm>
#include <cstring>
#include <functional>
+#include <unordered_map>
using namespace clang;
using namespace sema;
@@ -136,6 +138,7 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
+ case tok::kw___bf16:
case tok::kw__Float16:
case tok::kw___float128:
case tok::kw_wchar_t:
@@ -747,7 +750,10 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
Diag(IILoc, IsTemplateName ? diag::err_no_member_template
: diag::err_typename_nested_not_found)
<< II << DC << SS->getRange();
- else if (isDependentScopeSpecifier(*SS)) {
+ else if (SS->isValid() && SS->getScopeRep()->containsErrors()) {
+ SuggestedType =
+ ActOnTypenameType(S, SourceLocation(), *SS, *II, IILoc).get();
+ } else if (isDependentScopeSpecifier(*SS)) {
unsigned DiagID = diag::err_typename_missing;
if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S))
DiagID = diag::ext_typename_missing;
@@ -924,7 +930,7 @@ Corrected:
return NameClassification::NonType(D);
}
- if (getLangOpts().CPlusPlus2a && SS.isEmpty() && NextToken.is(tok::less)) {
+ if (getLangOpts().CPlusPlus20 && SS.isEmpty() && NextToken.is(tok::less)) {
// In C++20 onwards, this could be an ADL-only call to a function
// template, and we're required to assume that this is a template name.
//
@@ -1067,7 +1073,7 @@ Corrected:
Result, /*AllowFunctionTemplates=*/true,
/*AllowDependent=*/false,
/*AllowNonTemplateFunctions*/ SS.isEmpty() &&
- getLangOpts().CPlusPlus2a))) {
+ getLangOpts().CPlusPlus20))) {
// C++ [temp.names]p3:
// After name lookup (3.4) finds that a name is a template-name or that
// an operator-function-id or a literal- operator-id refers to a set of
@@ -1153,6 +1159,10 @@ Corrected:
return ParsedType::make(T);
}
+ if (isa<ConceptDecl>(FirstDecl))
+ return NameClassification::Concept(
+ TemplateName(cast<TemplateDecl>(FirstDecl)));
+
// We can have a type template here if we're classifying a template argument.
if (isa<TemplateDecl>(FirstDecl) && !isa<FunctionTemplateDecl>(FirstDecl) &&
!isa<VarTemplateDecl>(FirstDecl))
@@ -1250,47 +1260,8 @@ Sema::getTemplateNameKindForDiagnostics(TemplateName Name) {
return TemplateNameKindForDiagnostics::DependentTemplate;
}
-// Determines the context to return to after temporarily entering a
-// context. This depends in an unnecessarily complicated way on the
-// exact ordering of callbacks from the parser.
-DeclContext *Sema::getContainingDC(DeclContext *DC) {
-
- // Functions defined inline within classes aren't parsed until we've
- // finished parsing the top-level class, so the top-level class is
- // the context we'll need to return to.
- // A Lambda call operator whose parent is a class must not be treated
- // as an inline member function. A Lambda can be used legally
- // either as an in-class member initializer or a default argument. These
- // are parsed once the class has been marked complete and so the containing
- // context would be the nested class (when the lambda is defined in one);
- // If the class is not complete, then the lambda is being used in an
- // ill-formed fashion (such as to specify the width of a bit-field, or
- // in an array-bound) - in which case we still want to return the
- // lexically containing DC (which could be a nested class).
- if (isa<FunctionDecl>(DC) && !isLambdaCallOperator(DC)) {
- DC = DC->getLexicalParent();
-
- // A function not defined within a class will always return to its
- // lexical context.
- if (!isa<CXXRecordDecl>(DC))
- return DC;
-
- // A C++ inline method/friend is parsed *after* the topmost class
- // it was declared in is fully parsed ("complete"); the topmost
- // class is the context we need to return to.
- while (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC->getLexicalParent()))
- DC = RD;
-
- // Return the declaration context of the topmost class the inline method is
- // declared in.
- return DC;
- }
-
- return DC->getLexicalParent();
-}
-
void Sema::PushDeclContext(Scope *S, DeclContext *DC) {
- assert(getContainingDC(DC) == CurContext &&
+ assert(DC->getLexicalParent() == CurContext &&
"The next DeclContext should be lexically contained in the current one.");
CurContext = DC;
S->setEntity(DC);
@@ -1299,7 +1270,7 @@ void Sema::PushDeclContext(Scope *S, DeclContext *DC) {
void Sema::PopDeclContext() {
assert(CurContext && "DeclContext imbalance!");
- CurContext = getContainingDC(CurContext);
+ CurContext = CurContext->getLexicalParent();
assert(CurContext && "Popped translation unit!");
}
@@ -1351,6 +1322,12 @@ void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) {
CurContext = DC;
S->setEntity(DC);
+
+ if (S->getParent()->isTemplateParamScope()) {
+ // Also set the corresponding entities for all immediately-enclosing
+ // template parameter scopes.
+ EnterTemplatedContext(S->getParent(), DC);
+ }
}
void Sema::ExitDeclaratorContext(Scope *S) {
@@ -1366,6 +1343,49 @@ void Sema::ExitDeclaratorContext(Scope *S) {
// disappear.
}
+void Sema::EnterTemplatedContext(Scope *S, DeclContext *DC) {
+ assert(S->isTemplateParamScope() &&
+ "expected to be initializing a template parameter scope");
+
+ // C++20 [temp.local]p7:
+ // In the definition of a member of a class template that appears outside
+ // of the class template definition, the name of a member of the class
+ // template hides the name of a template-parameter of any enclosing class
+ // templates (but not a template-parameter of the member if the member is a
+ // class or function template).
+ // C++20 [temp.local]p9:
+ // In the definition of a class template or in the definition of a member
+ // of such a template that appears outside of the template definition, for
+ // each non-dependent base class (13.8.2.1), if the name of the base class
+ // or the name of a member of the base class is the same as the name of a
+ // template-parameter, the base class name or member name hides the
+ // template-parameter name (6.4.10).
+ //
+ // This means that a template parameter scope should be searched immediately
+ // after searching the DeclContext for which it is a template parameter
+ // scope. For example, for
+ // template<typename T> template<typename U> template<typename V>
+ // void N::A<T>::B<U>::f(...)
+ // we search V then B<U> (and base classes) then U then A<T> (and base
+ // classes) then T then N then ::.
+ unsigned ScopeDepth = getTemplateDepth(S);
+ for (; S && S->isTemplateParamScope(); S = S->getParent(), --ScopeDepth) {
+ DeclContext *SearchDCAfterScope = DC;
+ for (; DC; DC = DC->getLookupParent()) {
+ if (const TemplateParameterList *TPL =
+ cast<Decl>(DC)->getDescribedTemplateParams()) {
+ unsigned DCDepth = TPL->getDepth() + 1;
+ if (DCDepth > ScopeDepth)
+ continue;
+ if (ScopeDepth == DCDepth)
+ SearchDCAfterScope = DC = DC->getLookupParent();
+ break;
+ }
+ }
+ S->setLookupEntity(SearchDCAfterScope);
+ }
+}
+
void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) {
// We assume that the caller has already called
// ActOnReenterTemplateScope so getTemplatedDecl() works.
@@ -2586,11 +2606,15 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
AMK == Sema::AMK_ProtocolImplementation))
NewAttr = nullptr;
else if (const auto *UA = dyn_cast<UuidAttr>(Attr))
- NewAttr = S.mergeUuidAttr(D, *UA, UA->getGuid());
+ NewAttr = S.mergeUuidAttr(D, *UA, UA->getGuid(), UA->getGuidDecl());
else if (const auto *SLHA = dyn_cast<SpeculativeLoadHardeningAttr>(Attr))
NewAttr = S.mergeSpeculativeLoadHardeningAttr(D, *SLHA);
else if (const auto *SLHA = dyn_cast<NoSpeculativeLoadHardeningAttr>(Attr))
NewAttr = S.mergeNoSpeculativeLoadHardeningAttr(D, *SLHA);
+ else if (const auto *IMA = dyn_cast<WebAssemblyImportModuleAttr>(Attr))
+ NewAttr = S.mergeImportModuleAttr(D, *IMA);
+ else if (const auto *INA = dyn_cast<WebAssemblyImportNameAttr>(Attr))
+ NewAttr = S.mergeImportNameAttr(D, *INA);
else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr))
NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
@@ -2707,6 +2731,18 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
--E;
continue;
}
+ } else if (isa<LoaderUninitializedAttr>(NewAttribute)) {
+ // If there is a C definition followed by a redeclaration with this
+ // attribute then there are two different definitions. In C++, prefer the
+ // standard diagnostics.
+ if (!S.getLangOpts().CPlusPlus) {
+ S.Diag(NewAttribute->getLocation(),
+ diag::err_loader_uninitialized_redeclaration);
+ S.Diag(Def->getLocation(), diag::note_previous_definition);
+ NewAttributes.erase(NewAttributes.begin() + I);
+ --E;
+ continue;
+ }
} else if (isa<SelectAnyAttr>(NewAttribute) &&
cast<VarDecl>(New)->isInline() &&
!cast<VarDecl>(New)->isInlineSpecified()) {
@@ -2716,6 +2752,11 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
// honored it.
++I;
continue;
+ } else if (isa<OMPDeclareVariantAttr>(NewAttribute)) {
+ // We allow to add OMP[Begin]DeclareVariantAttr to be added to
+ // declarations after defintions.
+ ++I;
+ continue;
}
S.Diag(NewAttribute->getLocation(),
@@ -2736,23 +2777,21 @@ static void diagnoseMissingConstinit(Sema &S, const VarDecl *InitDecl,
// enough of the attribute list spelling information to extract that without
// heroics.
std::string SuitableSpelling;
- if (S.getLangOpts().CPlusPlus2a)
- SuitableSpelling =
- S.PP.getLastMacroWithSpelling(InsertLoc, {tok::kw_constinit});
+ if (S.getLangOpts().CPlusPlus20)
+ SuitableSpelling = std::string(
+ S.PP.getLastMacroWithSpelling(InsertLoc, {tok::kw_constinit}));
if (SuitableSpelling.empty() && S.getLangOpts().CPlusPlus11)
- SuitableSpelling = S.PP.getLastMacroWithSpelling(
- InsertLoc,
- {tok::l_square, tok::l_square, S.PP.getIdentifierInfo("clang"),
- tok::coloncolon,
- S.PP.getIdentifierInfo("require_constant_initialization"),
- tok::r_square, tok::r_square});
+ SuitableSpelling = std::string(S.PP.getLastMacroWithSpelling(
+ InsertLoc, {tok::l_square, tok::l_square,
+ S.PP.getIdentifierInfo("clang"), tok::coloncolon,
+ S.PP.getIdentifierInfo("require_constant_initialization"),
+ tok::r_square, tok::r_square}));
if (SuitableSpelling.empty())
- SuitableSpelling = S.PP.getLastMacroWithSpelling(
- InsertLoc,
- {tok::kw___attribute, tok::l_paren, tok::r_paren,
- S.PP.getIdentifierInfo("require_constant_initialization"),
- tok::r_paren, tok::r_paren});
- if (SuitableSpelling.empty() && S.getLangOpts().CPlusPlus2a)
+ SuitableSpelling = std::string(S.PP.getLastMacroWithSpelling(
+ InsertLoc, {tok::kw___attribute, tok::l_paren, tok::r_paren,
+ S.PP.getIdentifierInfo("require_constant_initialization"),
+ tok::r_paren, tok::r_paren}));
+ if (SuitableSpelling.empty() && S.getLangOpts().CPlusPlus20)
SuitableSpelling = "constinit";
if (SuitableSpelling.empty() && S.getLangOpts().CPlusPlus11)
SuitableSpelling = "[[clang::require_constant_initialization]]";
@@ -3884,11 +3923,11 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old,
if (!NewArray->isIncompleteArrayType() && !NewArray->isDependentType()) {
for (VarDecl *PrevVD = Old->getMostRecentDecl(); PrevVD;
PrevVD = PrevVD->getPreviousDecl()) {
- const ArrayType *PrevVDTy = Context.getAsArrayType(PrevVD->getType());
+ QualType PrevVDTy = PrevVD->getType();
if (PrevVDTy->isIncompleteArrayType() || PrevVDTy->isDependentType())
continue;
- if (!Context.hasSameType(NewArray, PrevVDTy))
+ if (!Context.hasSameType(New->getType(), PrevVDTy))
return diagnoseVarDeclTypeMismatch(*this, New, PrevVD);
}
}
@@ -4344,6 +4383,87 @@ void Sema::handleTagNumbering(const TagDecl *Tag, Scope *TagScope) {
}
}
+namespace {
+struct NonCLikeKind {
+ enum {
+ None,
+ BaseClass,
+ DefaultMemberInit,
+ Lambda,
+ Friend,
+ OtherMember,
+ Invalid,
+ } Kind = None;
+ SourceRange Range;
+
+ explicit operator bool() { return Kind != None; }
+};
+}
+
+/// Determine whether a class is C-like, according to the rules of C++
+/// [dcl.typedef] for anonymous classes with typedef names for linkage.
+static NonCLikeKind getNonCLikeKindForAnonymousStruct(const CXXRecordDecl *RD) {
+ if (RD->isInvalidDecl())
+ return {NonCLikeKind::Invalid, {}};
+
+ // C++ [dcl.typedef]p9: [P1766R1]
+ // An unnamed class with a typedef name for linkage purposes shall not
+ //
+ // -- have any base classes
+ if (RD->getNumBases())
+ return {NonCLikeKind::BaseClass,
+ SourceRange(RD->bases_begin()->getBeginLoc(),
+ RD->bases_end()[-1].getEndLoc())};
+ bool Invalid = false;
+ for (Decl *D : RD->decls()) {
+ // Don't complain about things we already diagnosed.
+ if (D->isInvalidDecl()) {
+ Invalid = true;
+ continue;
+ }
+
+ // -- have any [...] default member initializers
+ if (auto *FD = dyn_cast<FieldDecl>(D)) {
+ if (FD->hasInClassInitializer()) {
+ auto *Init = FD->getInClassInitializer();
+ return {NonCLikeKind::DefaultMemberInit,
+ Init ? Init->getSourceRange() : D->getSourceRange()};
+ }
+ continue;
+ }
+
+ // FIXME: We don't allow friend declarations. This violates the wording of
+ // P1766, but not the intent.
+ if (isa<FriendDecl>(D))
+ return {NonCLikeKind::Friend, D->getSourceRange()};
+
+ // -- declare any members other than non-static data members, member
+ // enumerations, or member classes,
+ if (isa<StaticAssertDecl>(D) || isa<IndirectFieldDecl>(D) ||
+ isa<EnumDecl>(D))
+ continue;
+ auto *MemberRD = dyn_cast<CXXRecordDecl>(D);
+ if (!MemberRD) {
+ if (D->isImplicit())
+ continue;
+ return {NonCLikeKind::OtherMember, D->getSourceRange()};
+ }
+
+ // -- contain a lambda-expression,
+ if (MemberRD->isLambda())
+ return {NonCLikeKind::Lambda, MemberRD->getSourceRange()};
+
+ // and all member classes shall also satisfy these requirements
+ // (recursively).
+ if (MemberRD->isThisDeclarationADefinition()) {
+ if (auto Kind = getNonCLikeKindForAnonymousStruct(MemberRD))
+ return Kind;
+ }
+ }
+
+ return {Invalid ? NonCLikeKind::Invalid : NonCLikeKind::None, {}};
+}
+
void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec,
TypedefNameDecl *NewTD) {
if (TagFromDeclSpec->isInvalidDecl())
@@ -4364,27 +4484,51 @@ void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec,
return;
}
- // If we've already computed linkage for the anonymous tag, then
- // adding a typedef name for the anonymous decl can change that
- // linkage, which might be a serious problem. Diagnose this as
- // unsupported and ignore the typedef name. TODO: we should
- // pursue this as a language defect and establish a formal rule
- // for how to handle it.
- if (TagFromDeclSpec->hasLinkageBeenComputed()) {
- Diag(NewTD->getLocation(), diag::err_typedef_changes_linkage);
+ // C++ [dcl.typedef]p9: [P1766R1, applied as DR]
+ // An unnamed class with a typedef name for linkage purposes shall [be
+ // C-like].
+ //
+ // FIXME: Also diagnose if we've already computed the linkage. That ideally
+ // shouldn't happen, but there are constructs that the language rule doesn't
+ // disallow for which we can't reasonably avoid computing linkage early.
+ const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TagFromDeclSpec);
+ NonCLikeKind NonCLike = RD ? getNonCLikeKindForAnonymousStruct(RD)
+ : NonCLikeKind();
+ bool ChangesLinkage = TagFromDeclSpec->hasLinkageBeenComputed();
+ if (NonCLike || ChangesLinkage) {
+ if (NonCLike.Kind == NonCLikeKind::Invalid)
+ return;
+
+ unsigned DiagID = diag::ext_non_c_like_anon_struct_in_typedef;
+ if (ChangesLinkage) {
+ // If the linkage changes, we can't accept this as an extension.
+ if (NonCLike.Kind == NonCLikeKind::None)
+ DiagID = diag::err_typedef_changes_linkage;
+ else
+ DiagID = diag::err_non_c_like_anon_struct_in_typedef;
+ }
- SourceLocation tagLoc = TagFromDeclSpec->getInnerLocStart();
- tagLoc = getLocForEndOfToken(tagLoc);
+ SourceLocation FixitLoc =
+ getLocForEndOfToken(TagFromDeclSpec->getInnerLocStart());
+ llvm::SmallString<40> TextToInsert;
+ TextToInsert += ' ';
+ TextToInsert += NewTD->getIdentifier()->getName();
- llvm::SmallString<40> textToInsert;
- textToInsert += ' ';
- textToInsert += NewTD->getIdentifier()->getName();
- Diag(tagLoc, diag::note_typedef_changes_linkage)
- << FixItHint::CreateInsertion(tagLoc, textToInsert);
- return;
+ Diag(FixitLoc, DiagID)
+ << isa<TypeAliasDecl>(NewTD)
+ << FixItHint::CreateInsertion(FixitLoc, TextToInsert);
+ if (NonCLike.Kind != NonCLikeKind::None) {
+ Diag(NonCLike.Range.getBegin(), diag::note_non_c_like_anon_struct)
+ << NonCLike.Kind - 1 << NonCLike.Range;
+ }
+ Diag(NewTD->getLocation(), diag::note_typedef_for_linkage_here)
+ << NewTD << isa<TypeAliasDecl>(NewTD);
+
+ if (ChangesLinkage)
+ return;
}
- // Otherwise, set this is the anon-decl typedef for the tag.
+ // Otherwise, set this as the anon-decl typedef for the tag.
TagFromDeclSpec->setTypedefNameForAnonDecl(NewTD);
}
@@ -4915,6 +5059,10 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// define non-static data members. [Note: nested types and
// functions cannot be declared within an anonymous union. ]
for (auto *Mem : Record->decls()) {
+ // Ignore invalid declarations; we already diagnosed them.
+ if (Mem->isInvalidDecl())
+ continue;
+
if (auto *FD = dyn_cast<FieldDecl>(Mem)) {
// C++ [class.union]p3:
// An anonymous union shall not have private or protected
@@ -5138,8 +5286,8 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
Chain.push_back(Anon);
RecordDecl *RecordDef = Record->getDefinition();
- if (RequireCompleteType(Anon->getLocation(), RecTy,
- diag::err_field_incomplete) ||
+ if (RequireCompleteSizedType(Anon->getLocation(), RecTy,
+ diag::err_field_incomplete_or_sizeless) ||
InjectAnonymousStructOrUnionMembers(*this, S, CurContext, RecordDef,
AS_none, Chain)) {
Anon->setInvalidDecl();
@@ -6142,6 +6290,8 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) {
void Sema::deduceOpenCLAddressSpace(ValueDecl *Decl) {
if (Decl->getType().hasAddressSpace())
return;
+ if (Decl->getType()->isDependentType())
+ return;
if (VarDecl *Var = dyn_cast<VarDecl>(Decl)) {
QualType Type = Var->getType();
if (Type->isSamplerT() || Type->isVoidType())
@@ -6468,6 +6618,8 @@ static bool shouldConsiderLinkage(const VarDecl *VD) {
return true;
if (DC->isRecord())
return false;
+ if (isa<RequiresExprBodyDecl>(DC))
+ return false;
llvm_unreachable("Unexpected context");
}
@@ -6753,28 +6905,49 @@ NamedDecl *Sema::ActOnVariableDeclarator(
if (SC == SC_Static && CurContext->isRecord()) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
- if (RD->isLocalClass())
+ // Walk up the enclosing DeclContexts to check for any that are
+ // incompatible with static data members.
+ const DeclContext *FunctionOrMethod = nullptr;
+ const CXXRecordDecl *AnonStruct = nullptr;
+ for (DeclContext *Ctxt = DC; Ctxt; Ctxt = Ctxt->getParent()) {
+ if (Ctxt->isFunctionOrMethod()) {
+ FunctionOrMethod = Ctxt;
+ break;
+ }
+ const CXXRecordDecl *ParentDecl = dyn_cast<CXXRecordDecl>(Ctxt);
+ if (ParentDecl && !ParentDecl->getDeclName()) {
+ AnonStruct = ParentDecl;
+ break;
+ }
+ }
+ if (FunctionOrMethod) {
+ // C++ [class.static.data]p5: A local class shall not have static data
+ // members.
Diag(D.getIdentifierLoc(),
diag::err_static_data_member_not_allowed_in_local_class)
- << Name << RD->getDeclName();
-
- // C++98 [class.union]p1: If a union contains a static data member,
- // the program is ill-formed. C++11 drops this restriction.
- if (RD->isUnion())
+ << Name << RD->getDeclName() << RD->getTagKind();
+ } else if (AnonStruct) {
+ // C++ [class.static.data]p4: Unnamed classes and classes contained
+ // directly or indirectly within unnamed classes shall not contain
+ // static data members.
+ Diag(D.getIdentifierLoc(),
+ diag::err_static_data_member_not_allowed_in_anon_struct)
+ << Name << AnonStruct->getTagKind();
+ Invalid = true;
+ } else if (RD->isUnion()) {
+ // C++98 [class.union]p1: If a union contains a static data member,
+ // the program is ill-formed. C++11 drops this restriction.
Diag(D.getIdentifierLoc(),
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_static_data_member_in_union
: diag::ext_static_data_member_in_union) << Name;
- // We conservatively disallow static data members in anonymous structs.
- else if (!RD->getDeclName())
- Diag(D.getIdentifierLoc(),
- diag::err_static_data_member_not_allowed_in_anon_struct)
- << Name << RD->isUnion();
+ }
}
}
// Match up the template parameter lists with the scope specifier, then
// determine whether we have a template or a template specialization.
+ bool InvalidScope = false;
TemplateParams = MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
D.getCXXScopeSpec(),
@@ -6782,7 +6955,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
? D.getName().TemplateId
: nullptr,
TemplateParamLists,
- /*never a friend*/ false, IsMemberSpecialization, Invalid);
+ /*never a friend*/ false, IsMemberSpecialization, InvalidScope);
+ Invalid |= InvalidScope;
if (TemplateParams) {
if (!TemplateParams->size() &&
@@ -6918,7 +7092,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
diag::err_thread_non_global)
<< DeclSpec::getSpecifierName(TSCS);
else if (!Context.getTargetInfo().isTLSSupported()) {
- if (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice) {
+ if (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice ||
+ getLangOpts().SYCLIsDevice) {
// Postpone error emission until we've collected attributes required to
// figure out whether it's a host or device variable and whether the
// error should be ignored.
@@ -6946,6 +7121,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
case CSK_constexpr:
NewVD->setConstexpr(true);
+ MaybeAddCUDAConstantAttr(NewVD);
// C++1z [dcl.spec.constexpr]p1:
// A static data member declared with the constexpr specifier is
// implicitly an inline variable.
@@ -7019,13 +7195,18 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewVD, D);
- if (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice) {
+ if (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice ||
+ getLangOpts().SYCLIsDevice) {
if (EmitTLSUnsupportedError &&
((getLangOpts().CUDA && DeclAttrsMatchCUDAMode(getLangOpts(), NewVD)) ||
(getLangOpts().OpenMPIsDevice &&
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(NewVD))))
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_thread_unsupported);
+
+ if (EmitTLSUnsupportedError &&
+ (LangOpts.SYCLIsDevice || (LangOpts.OpenMP && LangOpts.OpenMPIsDevice)))
+ targetDiag(D.getIdentifierLoc(), diag::err_thread_unsupported);
// CUDA B.2.5: "__shared__ and __constant__ variables have implied static
// storage [duration]."
if (SC == SC_None && S->getFnParent() != nullptr &&
@@ -7680,6 +7861,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
if (NewVD->isFileVarDecl() || NewVD->isStaticLocal() ||
NewVD->hasExternalStorage()) {
if (!T->isSamplerT() &&
+ !T->isDependentType() &&
!(T.getAddressSpace() == LangAS::opencl_constant ||
(T.getAddressSpace() == LangAS::opencl_global &&
(getLangOpts().OpenCLVersion == 200 ||
@@ -7822,6 +8004,12 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
return;
}
+ if (!NewVD->hasLocalStorage() && T->isSizelessType()) {
+ Diag(NewVD->getLocation(), diag::err_sizeless_nonlocal) << T;
+ NewVD->setInvalidDecl();
+ return;
+ }
+
if (isVM && NewVD->hasAttr<BlocksAttr>()) {
Diag(NewVD->getLocation(), diag::err_block_on_vm);
NewVD->setInvalidDecl();
@@ -7909,30 +8097,8 @@ struct FindOverriddenMethod {
return false;
}
};
-
-enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted };
} // end anonymous namespace
-/// Report an error regarding overriding, along with any relevant
-/// overridden methods.
-///
-/// \param DiagID the primary error to report.
-/// \param MD the overriding method.
-/// \param OEK which overrides to include as notes.
-static void ReportOverrides(Sema& S, unsigned DiagID, const CXXMethodDecl *MD,
- OverrideErrorKind OEK = OEK_All) {
- S.Diag(MD->getLocation(), DiagID) << MD->getDeclName();
- for (const CXXMethodDecl *O : MD->overridden_methods()) {
- // This check (& the OEK parameter) could be replaced by a predicate, but
- // without lambdas that would be overkill. This is still nicer than writing
- // out the diag loop 3 times.
- if ((OEK == OEK_All) ||
- (OEK == OEK_NonDeleted && !O->isDeleted()) ||
- (OEK == OEK_Deleted && O->isDeleted()))
- S.Diag(O->getLocation(), diag::note_overridden_virtual_function);
- }
-}
-
/// 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) {
@@ -7941,8 +8107,6 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
FindOverriddenMethod FOM;
FOM.Method = MD;
FOM.S = this;
- bool hasDeletedOverridenMethods = false;
- bool hasNonDeletedOverridenMethods = false;
bool AddedAny = false;
if (DC->lookupInBases(FOM, Paths)) {
for (auto *I : Paths.found_decls()) {
@@ -7952,21 +8116,12 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
!CheckOverridingFunctionAttributes(MD, OldMD) &&
!CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
!CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) {
- hasDeletedOverridenMethods |= OldMD->isDeleted();
- hasNonDeletedOverridenMethods |= !OldMD->isDeleted();
AddedAny = true;
}
}
}
}
- if (hasDeletedOverridenMethods && !MD->isDeleted()) {
- ReportOverrides(*this, diag::err_non_deleted_override, MD, OEK_Deleted);
- }
- if (hasNonDeletedOverridenMethods && MD->isDeleted()) {
- ReportOverrides(*this, diag::err_deleted_override, MD, OEK_NonDeleted);
- }
-
return AddedAny;
}
@@ -8654,11 +8809,24 @@ static Scope *getTagInjectionScope(Scope *S, const LangOptions &LangOpts) {
NamedDecl*
Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TypeSourceInfo *TInfo, LookupResult &Previous,
- MultiTemplateParamsArg TemplateParamLists,
+ MultiTemplateParamsArg TemplateParamListsRef,
bool &AddToScope) {
QualType R = TInfo->getType();
assert(R->isFunctionType());
+ if (R.getCanonicalType()->castAs<FunctionType>()->getCmseNSCallAttr())
+ Diag(D.getIdentifierLoc(), diag::err_function_decl_cmse_ns_call);
+
+ SmallVector<TemplateParameterList *, 4> TemplateParamLists;
+ for (TemplateParameterList *TPL : TemplateParamListsRef)
+ TemplateParamLists.push_back(TPL);
+ if (TemplateParameterList *Invented = D.getInventedTemplateParameterList()) {
+ if (!TemplateParamLists.empty() &&
+ Invented->getDepth() == TemplateParamLists.back()->getDepth())
+ TemplateParamLists.back() = Invented;
+ else
+ TemplateParamLists.push_back(Invented);
+ }
// TODO: consider using NameInfo for diagnostic.
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
@@ -8738,15 +8906,16 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Match up the template parameter lists with the scope specifier, then
// determine whether we have a template or a template specialization.
bool Invalid = false;
- if (TemplateParameterList *TemplateParams =
- MatchTemplateParametersToScopeSpecifier(
- D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
- D.getCXXScopeSpec(),
- D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
- ? D.getName().TemplateId
- : nullptr,
- TemplateParamLists, isFriend, isMemberSpecialization,
- Invalid)) {
+ TemplateParameterList *TemplateParams =
+ MatchTemplateParametersToScopeSpecifier(
+ D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
+ D.getCXXScopeSpec(),
+ D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
+ ? D.getName().TemplateId
+ : nullptr,
+ TemplateParamLists, isFriend, isMemberSpecialization,
+ Invalid);
+ if (TemplateParams) {
if (TemplateParams->size() > 0) {
// This is a function template
@@ -8779,7 +8948,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// For source fidelity, store the other template param lists.
if (TemplateParamLists.size() > 1) {
NewFD->setTemplateParameterListsInfo(Context,
- TemplateParamLists.drop_back(1));
+ ArrayRef<TemplateParameterList *>(TemplateParamLists)
+ .drop_back(1));
}
} else {
// This is a function template specialization.
@@ -8914,9 +9084,24 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// C++11 [dcl.constexpr]p3: functions declared constexpr are required to
// be either constructors or to return a literal type. Therefore,
// destructors cannot be declared constexpr.
- if (isa<CXXDestructorDecl>(NewFD) && !getLangOpts().CPlusPlus2a) {
+ if (isa<CXXDestructorDecl>(NewFD) &&
+ (!getLangOpts().CPlusPlus20 || ConstexprKind == CSK_consteval)) {
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor)
<< ConstexprKind;
+ NewFD->setConstexprKind(getLangOpts().CPlusPlus20 ? CSK_unspecified : CSK_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 &&
+ (NewFD->getOverloadedOperator() == OO_New ||
+ NewFD->getOverloadedOperator() == OO_Array_New ||
+ NewFD->getOverloadedOperator() == OO_Delete ||
+ NewFD->getOverloadedOperator() == OO_Array_Delete)) {
+ Diag(D.getDeclSpec().getConstexprSpecLoc(),
+ diag::err_invalid_consteval_decl_kind)
+ << NewFD;
+ NewFD->setConstexprKind(CSK_constexpr);
}
}
@@ -8945,8 +9130,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
// If a function is defined as defaulted or deleted, mark it as such now.
- // FIXME: Does this ever happen? ActOnStartOfFunctionDef forces the function
- // definition kind to FDK_Definition.
+ // We'll do the relevant checks on defaulted / deleted functions later.
switch (D.getFunctionDefinitionKind()) {
case FDK_Declaration:
case FDK_Definition:
@@ -9808,6 +9992,18 @@ static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) {
return false;
}
+// Provide a white-list of attributes that are allowed to be combined with
+// multiversion functions.
+static bool AttrCompatibleWithMultiVersion(attr::Kind Kind,
+ MultiVersionKind MVType) {
+ switch (Kind) {
+ default:
+ return false;
+ case attr::Used:
+ return MVType == MultiVersionKind::Target;
+ }
+}
+
static bool HasNonMultiVersionAttributes(const FunctionDecl *FD,
MultiVersionKind MVType) {
for (const Attr *A : FD->attrs()) {
@@ -9823,7 +10019,9 @@ static bool HasNonMultiVersionAttributes(const FunctionDecl *FD,
return true;
break;
default:
- return true;
+ if (!AttrCompatibleWithMultiVersion(A->getKind(), MVType))
+ return true;
+ break;
}
}
return false;
@@ -10562,9 +10760,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
return Redeclaration;
}
}
- } else if (CXXConversionDecl *Conversion
- = dyn_cast<CXXConversionDecl>(NewFD)) {
- ActOnConversionDeclarator(Conversion);
} else if (auto *Guide = dyn_cast<CXXDeductionGuideDecl>(NewFD)) {
if (auto *TD = Guide->getDescribedFunctionTemplate())
CheckDeductionGuideTemplate(TD);
@@ -10581,12 +10776,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
if (!Method->isFunctionTemplateSpecialization() &&
!Method->getDescribedFunctionTemplate() &&
Method->isCanonicalDecl()) {
- if (AddOverriddenMethods(Method->getParent(), Method)) {
- // If the function was marked as "static", we have a problem.
- if (NewFD->getStorageClass() == SC_Static) {
- ReportOverrides(*this, diag::err_static_overrides_virtual, Method);
- }
- }
+ AddOverriddenMethods(Method->getParent(), Method);
}
if (Method->isVirtual() && NewFD->getTrailingRequiresClause())
// C++2a [class.virtual]p6
@@ -10598,6 +10788,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
checkThisInStaticMemberFunctionType(Method);
}
+ if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
+ ActOnConversionDeclarator(Conversion);
+
// Extra checking for C++ overloaded operators (C++ [over.oper]).
if (NewFD->isOverloadedOperator() &&
CheckOverloadedOperatorDeclaration(NewFD)) {
@@ -11363,6 +11556,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit,
Expr *Init) {
+ assert(!Init || !Init->containsErrors());
QualType DeducedType = deduceVarTypeFromInitializer(
VDecl, VDecl->getDeclName(), VDecl->getType(), VDecl->getTypeSourceInfo(),
VDecl->getSourceRange(), DirectInit, Init);
@@ -11396,6 +11590,9 @@ bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit,
void Sema::checkNonTrivialCUnionInInitializer(const Expr *Init,
SourceLocation Loc) {
+ if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))
+ Init = EWC->getSubExpr();
+
if (auto *CE = dyn_cast<ConstantExpr>(Init))
Init = CE->getSubExpr();
@@ -11698,7 +11895,15 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// TypoExpr.
ExprResult Res = CorrectDelayedTyposInExpr(Init, VDecl);
if (!Res.isUsable()) {
+ // There are unresolved typos in Init, just drop them.
+ // FIXME: improve the recovery strategy to preserve the Init.
+ RealDecl->setInvalidDecl();
+ return;
+ }
+ if (Res.get()->containsErrors()) {
+ // Invalidate the decl as we don't know the type for recovery-expr yet.
RealDecl->setInvalidDecl();
+ VDecl->setInit(Res.get());
return;
}
Init = Res.get();
@@ -11790,6 +11995,13 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
return;
}
+ // The LoaderUninitialized attribute acts as a definition (of undef).
+ if (VDecl->hasAttr<LoaderUninitializedAttr>()) {
+ Diag(VDecl->getLocation(), diag::err_loader_uninitialized_cant_init);
+ VDecl->setInvalidDecl();
+ return;
+ }
+
// Get the decls type and save a reference for later, since
// CheckInitializerTypes may change it.
QualType DclT = VDecl->getType(), SavT = DclT;
@@ -11821,7 +12033,8 @@ 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, [this, Entity, Kind](Expr *E) {
+ Args[Idx], VDecl, /*RecoverUncorrectedTypos=*/false,
+ [this, Entity, Kind](Expr *E) {
InitializationSequence Init(*this, Entity, Kind, MultiExprArg(E));
return Init.Failed() ? ExprError() : E;
});
@@ -11839,7 +12052,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
/*TreatUnavailableAsInvalid=*/false);
ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT);
if (Result.isInvalid()) {
- VDecl->setInvalidDecl();
+ // If the provied initializer fails to initialize the var decl,
+ // we attach a recovery expr for better recovery.
+ auto RecoveryExpr =
+ CreateRecoveryExpr(Init->getBeginLoc(), Init->getEndLoc(), Args);
+ if (RecoveryExpr.get())
+ VDecl->setInit(RecoveryExpr.get());
return;
}
@@ -12100,6 +12318,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
VDecl->setInitStyle(VarDecl::ListInit);
}
+ if (LangOpts.OpenMP && VDecl->isFileVarDecl())
+ DeclsToCheckForDeferredDiags.push_back(VDecl);
CheckCompleteVariableDeclaration(VDecl);
}
@@ -12120,7 +12340,7 @@ void Sema::ActOnInitializerError(Decl *D) {
BD->setInvalidDecl();
// Auto types are meaningless if we can't make sense of the initializer.
- if (ParsingInitForAutoVars.count(D)) {
+ if (VD->getType()->isUndeducedType()) {
D->setInvalidDecl();
return;
}
@@ -12203,6 +12423,22 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
return;
}
+ if (!Var->isInvalidDecl() && RealDecl->hasAttr<LoaderUninitializedAttr>()) {
+ if (CXXRecordDecl *RD = Var->getType()->getAsCXXRecordDecl()) {
+ if (!RD->hasTrivialDefaultConstructor()) {
+ Diag(Var->getLocation(), diag::err_loader_uninitialized_trivial_ctor);
+ Var->setInvalidDecl();
+ return;
+ }
+ }
+ if (Var->getStorageClass() == SC_Extern) {
+ Diag(Var->getLocation(), diag::err_loader_uninitialized_extern_decl)
+ << Var;
+ Var->setInvalidDecl();
+ return;
+ }
+ }
+
VarDecl::DefinitionKind DefKind = Var->isThisDeclarationADefinition();
if (!Var->isInvalidDecl() && DefKind != VarDecl::DeclarationOnly &&
Var->getType().hasNonTrivialToPrimitiveDefaultInitializeCUnion())
@@ -12260,9 +12496,9 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
if (!Var->isInvalidDecl()) {
if (const IncompleteArrayType *ArrayT
= Context.getAsIncompleteArrayType(Type)) {
- if (RequireCompleteType(Var->getLocation(),
- ArrayT->getElementType(),
- diag::err_illegal_decl_array_incomplete_type))
+ if (RequireCompleteSizedType(
+ Var->getLocation(), ArrayT->getElementType(),
+ diag::err_array_incomplete_or_sizeless_type))
Var->setInvalidDecl();
} else if (Var->getStorageClass() == SC_Static) {
// C99 6.9.2p3: If the declaration of an identifier for an object is
@@ -12378,12 +12614,18 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
InitializationSequence InitSeq(*this, Entity, Kind, None);
ExprResult Init = InitSeq.Perform(*this, Entity, Kind, None);
- if (Init.isInvalid())
- Var->setInvalidDecl();
- else if (Init.get()) {
+
+ if (Init.get()) {
Var->setInit(MaybeCreateExprWithCleanups(Init.get()));
// This is important for template substitution.
Var->setInitStyle(VarDecl::CallInit);
+ } else if (Init.isInvalid()) {
+ // If default-init fails, attach a recovery-expr initializer to track
+ // that initialization was attempted and failed.
+ auto RecoveryExpr =
+ CreateRecoveryExpr(Var->getLocation(), Var->getLocation(), {});
+ if (RecoveryExpr.get())
+ Var->setInit(RecoveryExpr.get());
}
CheckCompleteVariableDeclaration(Var);
@@ -12507,6 +12749,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
var->getDeclContext()->getRedeclContext()->isFileContext() &&
var->isExternallyVisible() && var->hasLinkage() &&
!var->isInline() && !var->getDescribedVarTemplate() &&
+ !isa<VarTemplatePartialSpecializationDecl>(var) &&
!isTemplateInstantiation(var->getTemplateSpecializationKind()) &&
!getDiagnostics().isIgnored(diag::warn_missing_variable_declarations,
var->getLocation())) {
@@ -12559,7 +12802,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
if (GlobalStorage && var->isThisDeclarationADefinition() &&
!inTemplateInstantiation()) {
PragmaStack<StringLiteral *> *Stack = nullptr;
- int SectionFlags = ASTContext::PSF_Implicit | ASTContext::PSF_Read;
+ int SectionFlags = ASTContext::PSF_Read;
if (var->getType().isConstQualified())
Stack = &ConstSegStack;
else if (!var->getInit()) {
@@ -12569,14 +12812,19 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
Stack = &DataSegStack;
SectionFlags |= ASTContext::PSF_Write;
}
- if (Stack->CurrentValue && !var->hasAttr<SectionAttr>())
+ if (const SectionAttr *SA = var->getAttr<SectionAttr>()) {
+ if (SA->getSyntax() == AttributeCommonInfo::AS_Declspec)
+ SectionFlags |= ASTContext::PSF_Implicit;
+ UnifySection(SA->getName(), SectionFlags, var);
+ } else if (Stack->CurrentValue) {
+ SectionFlags |= ASTContext::PSF_Implicit;
+ auto SectionName = Stack->CurrentValue->getString();
var->addAttr(SectionAttr::CreateImplicit(
- Context, Stack->CurrentValue->getString(),
- Stack->CurrentPragmaLocation, AttributeCommonInfo::AS_Pragma,
- SectionAttr::Declspec_allocate));
- if (const SectionAttr *SA = var->getAttr<SectionAttr>())
- if (UnifySection(SA->getName(), SectionFlags, var))
+ Context, SectionName, Stack->CurrentPragmaLocation,
+ AttributeCommonInfo::AS_Pragma, SectionAttr::Declspec_allocate));
+ if (UnifySection(SectionName, SectionFlags, var))
var->dropAttr<SectionAttr>();
+ }
// Apply the init_seg attribute if this has an initializer. If the
// initializer turns out to not be dynamic, we'll end up ignoring this
@@ -13013,13 +13261,15 @@ Sema::BuildDeclaratorGroup(MutableArrayRef<Decl *> Group) {
DeducedDecl = D;
} else if (!Context.hasSameType(DT->getDeducedType(), Deduced)) {
auto *AT = dyn_cast<AutoType>(DT);
- Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
- diag::err_auto_different_deductions)
- << (AT ? (unsigned)AT->getKeyword() : 3)
- << Deduced << DeducedDecl->getDeclName()
- << DT->getDeducedType() << D->getDeclName()
- << DeducedDecl->getInit()->getSourceRange()
- << D->getInit()->getSourceRange();
+ auto Dia = Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
+ diag::err_auto_different_deductions)
+ << (AT ? (unsigned)AT->getKeyword() : 3) << Deduced
+ << DeducedDecl->getDeclName() << DT->getDeducedType()
+ << D->getDeclName();
+ if (DeducedDecl->hasInit())
+ Dia << DeducedDecl->getInit()->getSourceRange();
+ if (D->getInit())
+ Dia << D->getInit()->getSourceRange();
D->setInvalidDecl();
break;
}
@@ -13398,9 +13648,28 @@ Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D,
assert(D.isFunctionDeclarator() && "Not a function declarator!");
Scope *ParentScope = FnBodyScope->getParent();
+ // Check if we are in an `omp begin/end declare variant` scope. If we are, and
+ // we define a non-templated function definition, we will create a declaration
+ // instead (=BaseFD), and emit the definition with a mangled name afterwards.
+ // The base function declaration will have the equivalent of an `omp declare
+ // 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);
+
D.setFunctionDefinitionKind(FDK_Definition);
Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists);
- return ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody);
+ Decl *Dcl = ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody);
+
+ if (BaseFD)
+ ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
+ cast<FunctionDecl>(Dcl), BaseFD);
+
+ return Dcl;
}
void Sema::ActOnFinishInlineFunctionDef(FunctionDecl *D) {
@@ -13593,13 +13862,12 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
VarDecl *VD = C.getCapturedVar();
if (VD->isInitCapture())
S.CurrentInstantiationScope->InstantiatedLocal(VD, VD);
- QualType CaptureType = VD->getType();
const bool ByRef = C.getCaptureKind() == LCK_ByRef;
LSI->addCapture(VD, /*IsBlock*/false, ByRef,
/*RefersToEnclosingVariableOrCapture*/true, C.getLocation(),
/*EllipsisLoc*/C.isPackExpansion()
? C.getEllipsisLoc() : SourceLocation(),
- CaptureType, /*Invalid*/false);
+ I->getType(), /*Invalid*/false);
} else if (C.capturesThis()) {
LSI->addThisCapture(/*Nested*/ false, C.getLocation(), I->getType(),
@@ -13632,7 +13900,9 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
// Do not push if it is a lambda because one is already pushed when building
// the lambda in ActOnStartOfLambdaDefinition().
if (!isLambdaCallOperator(FD))
- PushExpressionEvaluationContext(ExprEvalContexts.back().Context);
+ PushExpressionEvaluationContext(
+ FD->isConsteval() ? ExpressionEvaluationContext::ConstantEvaluated
+ : ExprEvalContexts.back().Context);
// Check for defining attributes before the check for redefinition.
if (const auto *Attr = FD->getAttr<AliasAttr>()) {
@@ -13996,11 +14266,48 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
: 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;
+
+ if (LocInfo.second > Buffer.size())
+ return false;
+
+ 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("//"));
+ };
+
+ 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()))
+
+ return FD->getBeginLoc();
+ }
+ return FD->getTypeSpecStartLoc();
+ };
Diag(FD->getTypeSpecStartLoc(), diag::note_static_for_internal_linkage)
<< /* function */ 1
<< (FD->getStorageClass() == SC_None
- ? FixItHint::CreateInsertion(FD->getTypeSpecStartLoc(),
- "static ")
+ ? FixItHint::CreateInsertion(findBeginLoc(), "static ")
: FixItHint{});
}
@@ -14008,11 +14315,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
// 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.
- // An empty list in a function declarator that is part of a definition
- // of that function specifies that the function has no parameters
- // (C99 6.7.5.3p14)
- if (!FD->hasWrittenPrototype() && FD->getNumParams() > 0 &&
- !LangOpts.CPlusPlus) {
+ if (!FD->hasWrittenPrototype()) {
TypeSourceInfo *TI = FD->getTypeSourceInfo();
TypeLoc TL = TI->getTypeLoc();
FunctionTypeLoc FTL = TL.getAsAdjusted<FunctionTypeLoc>();
@@ -14142,7 +14445,7 @@ 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().hasErrorOccurred() ||
+ if (getDiagnostics().hasUncompilableErrorOccurred() ||
getDiagnostics().getSuppressAllDiagnostics()) {
DiscardCleanupsInEvaluationContext();
}
@@ -14198,10 +14501,17 @@ 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().hasErrorOccurred()) {
+ if (getDiagnostics().hasUncompilableErrorOccurred()) {
DiscardCleanupsInEvaluationContext();
}
+ if (LangOpts.OpenMP || LangOpts.CUDA || LangOpts.SYCLIsDevice) {
+ auto ES = getEmissionStatus(FD);
+ if (ES == Sema::FunctionEmissionStatus::Emitted ||
+ ES == Sema::FunctionEmissionStatus::Unknown)
+ DeclsToCheckForDeferredDiags.push_back(FD);
+ }
+
return dcl;
}
@@ -14333,6 +14643,77 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
return FD;
}
+/// If this function is a C++ replaceable global allocation function
+/// (C++2a [basic.stc.dynamic.allocation], C++2a [new.delete]),
+/// adds any function attributes that we know a priori based on the standard.
+///
+/// We need to check for duplicate attributes both here and where user-written
+/// attributes are applied to declarations.
+void Sema::AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(
+ FunctionDecl *FD) {
+ if (FD->isInvalidDecl())
+ return;
+
+ if (FD->getDeclName().getCXXOverloadedOperator() != OO_New &&
+ FD->getDeclName().getCXXOverloadedOperator() != OO_Array_New)
+ return;
+
+ Optional<unsigned> AlignmentParam;
+ bool IsNothrow = false;
+ if (!FD->isReplaceableGlobalAllocationFunction(&AlignmentParam, &IsNothrow))
+ return;
+
+ // C++2a [basic.stc.dynamic.allocation]p4:
+ // An allocation function that has a non-throwing exception specification
+ // indicates failure by returning a null pointer value. Any other allocation
+ // function never returns a null pointer value and indicates failure only by
+ // throwing an exception [...]
+ if (!IsNothrow && !FD->hasAttr<ReturnsNonNullAttr>())
+ FD->addAttr(ReturnsNonNullAttr::CreateImplicit(Context, FD->getLocation()));
+
+ // C++2a [basic.stc.dynamic.allocation]p2:
+ // An allocation function attempts to allocate the requested amount of
+ // storage. [...] If the request succeeds, the value returned by a
+ // replaceable allocation function is a [...] pointer value p0 different
+ // from any previously returned value p1 [...]
+ //
+ // However, this particular information is being added in codegen,
+ // because there is an opt-out switch for it (-fno-assume-sane-operator-new)
+
+ // C++2a [basic.stc.dynamic.allocation]p2:
+ // An allocation function attempts to allocate the requested amount of
+ // storage. If it is successful, it returns the address of the start of a
+ // block of storage whose length in bytes is at least as large as the
+ // requested size.
+ if (!FD->hasAttr<AllocSizeAttr>()) {
+ FD->addAttr(AllocSizeAttr::CreateImplicit(
+ Context, /*ElemSizeParam=*/ParamIdx(1, FD),
+ /*NumElemsParam=*/ParamIdx(), FD->getLocation()));
+ }
+
+ // C++2a [basic.stc.dynamic.allocation]p3:
+ // For an allocation function [...], the pointer returned on a successful
+ // call shall represent the address of storage that is aligned as follows:
+ // (3.1) If the allocation function takes an argument of type
+ // std​::​align_­val_­t, the storage will have the alignment
+ // specified by the value of this argument.
+ if (AlignmentParam.hasValue() && !FD->hasAttr<AllocAlignAttr>()) {
+ FD->addAttr(AllocAlignAttr::CreateImplicit(
+ Context, ParamIdx(AlignmentParam.getValue(), FD), FD->getLocation()));
+ }
+
+ // FIXME:
+ // C++2a [basic.stc.dynamic.allocation]p3:
+ // For an allocation function [...], the pointer returned on a successful
+ // call shall represent the address of storage that is aligned as follows:
+ // (3.2) Otherwise, if the allocation function is named operator new[],
+ // the storage is aligned for any object that does not have
+ // new-extended alignment ([basic.align]) and is no larger than the
+ // requested size.
+ // (3.3) Otherwise, the storage is aligned for any object that does not
+ // have new-extended alignment and is of the requested size.
+}
+
/// Adds any function attributes that we know a priori based on
/// the declaration of this function.
///
@@ -14433,6 +14814,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
}
}
+ AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(FD);
+
// If C++ exceptions are enabled but we are told extern "C" functions cannot
// throw, add an implicit nothrow attribute to any extern "C" function we come
// across.
@@ -14538,12 +14921,16 @@ bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) {
if (T->isDependentType())
return false;
+ // This doesn't use 'isIntegralType' despite the error message mentioning
+ // integral type because isIntegralType would also allow enum types in C.
if (const BuiltinType *BT = T->getAs<BuiltinType>())
if (BT->isInteger())
return false;
- Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) << T;
- return true;
+ if (T->isExtIntType())
+ return false;
+
+ return Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) << T;
}
/// Check whether this is a valid redeclaration of a previous enumeration.
@@ -15302,16 +15689,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (Kind == TTK_Enum && PrevTagDecl->getTagKind() == TTK_Enum) {
const EnumDecl *PrevEnum = cast<EnumDecl>(PrevTagDecl);
-
- // If this is an elaborated-type-specifier for a scoped enumeration,
- // the 'class' keyword is not necessary and not permitted.
- if (TUK == TUK_Reference || TUK == TUK_Friend) {
- if (ScopedEnum)
- Diag(ScopedEnumKWLoc, diag::err_enum_class_reference)
- << PrevEnum->isScoped()
- << FixItHint::CreateRemoval(ScopedEnumKWLoc);
+ if (TUK == TUK_Reference || TUK == TUK_Friend)
return PrevTagDecl;
- }
QualType EnumUnderlyingTy;
if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo*>())
@@ -15789,7 +16168,7 @@ Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) {
assert(isa<ObjCContainerDecl>(IDecl) &&
"ActOnObjCContainerStartDefinition - Not ObjCContainerDecl");
DeclContext *OCD = cast<DeclContext>(IDecl);
- assert(getContainingDC(OCD) == CurContext &&
+ assert(OCD->getLexicalParent() == CurContext &&
"The next DeclContext should be lexically contained in the current one.");
CurContext = OCD;
return IDecl;
@@ -15900,6 +16279,10 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
IdentifierInfo *FieldName,
QualType FieldTy, bool IsMsStruct,
Expr *BitWidth, bool *ZeroWidth) {
+ assert(BitWidth);
+ if (BitWidth->containsErrors())
+ return ExprError();
+
// Default to true; that shouldn't confuse checks for emptiness
if (ZeroWidth)
*ZeroWidth = true;
@@ -15907,8 +16290,9 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
// C99 6.7.2.1p4 - verify the field type.
// C++ 9.6p3: A bit-field shall have integral or enumeration type.
if (!FieldTy->isDependentType() && !FieldTy->isIntegralOrEnumerationType()) {
- // Handle incomplete types with specific error.
- if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete))
+ // Handle incomplete and sizeless types with a specific error.
+ if (RequireCompleteSizedType(FieldLoc, FieldTy,
+ diag::err_field_incomplete_or_sizeless))
return ExprError();
if (FieldName)
return Diag(FieldLoc, diag::err_not_integral_type_bitfield)
@@ -16118,14 +16502,15 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
// If we receive a broken type, recover by assuming 'int' and
// marking this declaration as invalid.
- if (T.isNull()) {
+ if (T.isNull() || T->containsErrors()) {
InvalidDecl = true;
T = Context.IntTy;
}
QualType EltTy = Context.getBaseElementType(T);
- if (!EltTy->isDependentType()) {
- if (RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) {
+ if (!EltTy->isDependentType() && !EltTy->containsErrors()) {
+ if (RequireCompleteSizedType(Loc, EltTy,
+ diag::err_field_incomplete_or_sizeless)) {
// Fields of incomplete type force their record to be invalid.
Record->setInvalidDecl();
InvalidDecl = true;
@@ -16214,6 +16599,14 @@ 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.
@@ -16669,8 +17062,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
// elsewhere, after synthesized ivars are known.
}
} else if (!FDTy->isDependentType() &&
- RequireCompleteType(FD->getLocation(), FD->getType(),
- diag::err_field_incomplete)) {
+ RequireCompleteSizedType(
+ FD->getLocation(), FD->getType(),
+ diag::err_field_incomplete_or_sizeless)) {
// Incomplete type
FD->setInvalidDecl();
EnclosingDecl->setInvalidDecl();
@@ -16728,8 +17122,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
Context, "", UnavailableAttr::IR_ARCFieldWithOwnership,
FD->getLocation()));
} else if (getLangOpts().ObjC &&
- getLangOpts().getGC() != LangOptions::NonGC &&
- Record && !Record->hasObjectMember()) {
+ getLangOpts().getGC() != LangOptions::NonGC && Record &&
+ !Record->hasObjectMember()) {
if (FD->getType()->isObjCObjectPointerType() ||
FD->getType().isObjCGCStrong())
Record->setHasObjectMember(true);
@@ -16793,10 +17187,10 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
I.setAccess((*I)->getAccess());
}
- if (!CXXRecord->isDependentType()) {
- // Add any implicitly-declared members to this class.
- AddImplicitlyDeclaredMembersToClass(CXXRecord);
+ // Add any implicitly-declared members to this class.
+ AddImplicitlyDeclaredMembersToClass(CXXRecord);
+ if (!CXXRecord->isDependentType()) {
if (!CXXRecord->isInvalidDecl()) {
// If we have virtual base classes, we may end up finding multiple
// final overriders for a given virtual function. Check for this
@@ -17355,9 +17749,11 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
typedef SmallVector<std::unique_ptr<ECDVector>, 3> DuplicatesVector;
typedef llvm::PointerUnion<EnumConstantDecl*, ECDVector*> DeclOrVector;
+
+ // DenseMaps cannot contain the all ones int64_t value, so use unordered_map.
typedef std::unordered_map<int64_t, DeclOrVector> ValueToVectorMap;
- // Use int64_t as a key to avoid needing special handling for DenseMap keys.
+ // Use int64_t as a key to avoid needing special handling for map keys.
auto EnumConstantToKey = [](const EnumConstantDecl *D) {
llvm::APSInt Val = D->getInitVal();
return Val.isSigned() ? Val.getSExtValue() : Val.getZExtValue();
@@ -17787,7 +18183,13 @@ Decl *Sema::getObjCDeclContext() const {
return (dyn_cast_or_null<ObjCContainerDecl>(CurContext));
}
-Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD) {
+Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD,
+ bool Final) {
+ // SYCL functions can be template, so we check if they have appropriate
+ // attribute prior to checking if it is a template.
+ if (LangOpts.SYCLIsDevice && FD->hasAttr<SYCLKernelAttr>())
+ return FunctionEmissionStatus::Emitted;
+
// Templates are emitted when they're instantiated.
if (FD->isDependentContext())
return FunctionEmissionStatus::TemplateDiscarded;
@@ -17799,8 +18201,10 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD) {
if (DevTy.hasValue()) {
if (*DevTy == OMPDeclareTargetDeclAttr::DT_Host)
OMPES = FunctionEmissionStatus::OMPDiscarded;
- else if (DeviceKnownEmittedFns.count(FD) > 0)
+ 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.
@@ -17816,10 +18220,11 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD) {
if (DevTy.hasValue()) {
if (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
OMPES = FunctionEmissionStatus::OMPDiscarded;
- } else if (DeviceKnownEmittedFns.count(FD) > 0) {
+ } else if (*DevTy == OMPDeclareTargetDeclAttr::DT_Host ||
+ *DevTy == OMPDeclareTargetDeclAttr::DT_Any)
OMPES = FunctionEmissionStatus::Emitted;
- }
- }
+ } else if (Final)
+ OMPES = FunctionEmissionStatus::Emitted;
}
}
if (OMPES == FunctionEmissionStatus::OMPDiscarded ||
@@ -17854,9 +18259,7 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD) {
// Otherwise, the function is known-emitted if it's in our set of
// known-emitted functions.
- return (DeviceKnownEmittedFns.count(FD) > 0)
- ? FunctionEmissionStatus::Emitted
- : FunctionEmissionStatus::Unknown;
+ return FunctionEmissionStatus::Unknown;
}
bool Sema::shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee) {