summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--lib/Sema/SemaDeclCXX.cpp1150
1 files changed, 771 insertions, 379 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index aa26b37f444d..4cf3abdf5745 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
+#include "clang/AST/ComparisonCategories.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
@@ -170,43 +171,40 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
if (EST == EST_None && Method->hasAttr<NoThrowAttr>())
EST = EST_BasicNoexcept;
- switch(EST) {
+ switch (EST) {
+ case EST_Unparsed:
+ case EST_Uninstantiated:
+ case EST_Unevaluated:
+ llvm_unreachable("should not see unresolved exception specs here");
+
// If this function can throw any exceptions, make a note of that.
case EST_MSAny:
case EST_None:
+ // FIXME: Whichever we see last of MSAny and None determines our result.
+ // We should make a consistent, order-independent choice here.
ClearExceptions();
ComputedEST = EST;
return;
+ case EST_NoexceptFalse:
+ ClearExceptions();
+ ComputedEST = EST_None;
+ return;
// FIXME: If the call to this decl is using any of its default arguments, we
// need to search them for potentially-throwing calls.
// If this function has a basic noexcept, it doesn't affect the outcome.
case EST_BasicNoexcept:
+ case EST_NoexceptTrue:
return;
- // If we're still at noexcept(true) and there's a nothrow() callee,
+ // If we're still at noexcept(true) and there's a throw() callee,
// change to that specification.
case EST_DynamicNone:
if (ComputedEST == EST_BasicNoexcept)
ComputedEST = EST_DynamicNone;
return;
- // Check out noexcept specs.
- case EST_ComputedNoexcept:
- {
- FunctionProtoType::NoexceptResult NR =
- Proto->getNoexceptSpec(Self->Context);
- assert(NR != FunctionProtoType::NR_NoNoexcept &&
- "Must have noexcept result for EST_ComputedNoexcept.");
- assert(NR != FunctionProtoType::NR_Dependent &&
- "Should not generate implicit declarations for dependent cases, "
- "and don't know how to handle them anyway.");
- // noexcept(false) -> no spec on the new function
- if (NR == FunctionProtoType::NR_Throw) {
- ClearExceptions();
- ComputedEST = EST_None;
- }
- // noexcept(true) won't change anything either.
- return;
- }
- default:
+ case EST_DependentNoexcept:
+ llvm_unreachable(
+ "should not generate implicit declarations for dependent cases");
+ case EST_Dynamic:
break;
}
assert(EST == EST_Dynamic && "EST case not considered earlier.");
@@ -712,7 +710,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
Diag(Decomp.getLSquareLoc(),
!getLangOpts().CPlusPlus17
? diag::ext_decomp_decl
- : D.getContext() == Declarator::ConditionContext
+ : D.getContext() == DeclaratorContext::ConditionContext
? diag::ext_decomp_decl_cond
: diag::warn_cxx14_compat_decomp_decl)
<< Decomp.getSourceRange();
@@ -1459,7 +1457,7 @@ void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) {
DD->setInvalidDecl();
}
-/// \brief Merge the exception specifications of two variable declarations.
+/// Merge the exception specifications of two variable declarations.
///
/// This is called when there's a redeclaration of a VarDecl. The function
/// checks if the redeclaration might have an exception specification and
@@ -1575,7 +1573,7 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
return true;
}
-/// \brief Get diagnostic %select index for tag kind for
+/// Get diagnostic %select index for tag kind for
/// record diagnostic message.
/// WARNING: Indexes apply to particular diagnostics only!
///
@@ -2061,27 +2059,39 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
return true;
}
+/// Get the class that is directly named by the current context. This is the
+/// class for which an unqualified-id in this scope could name a constructor
+/// or destructor.
+///
+/// If the scope specifier denotes a class, this will be that class.
+/// If the scope specifier is empty, this will be the class whose
+/// member-specification we are currently within. Otherwise, there
+/// is no such class.
+CXXRecordDecl *Sema::getCurrentClass(Scope *, const CXXScopeSpec *SS) {
+ assert(getLangOpts().CPlusPlus && "No class names in C!");
+
+ if (SS && SS->isInvalid())
+ return nullptr;
+
+ if (SS && SS->isNotEmpty()) {
+ DeclContext *DC = computeDeclContext(*SS, true);
+ return dyn_cast_or_null<CXXRecordDecl>(DC);
+ }
+
+ return dyn_cast_or_null<CXXRecordDecl>(CurContext);
+}
+
/// isCurrentClassName - Determine whether the identifier II is the
/// name of the class type currently being defined. In the case of
/// nested classes, this will only return true if II is the name of
/// the innermost class.
-bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *,
+bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS) {
- assert(getLangOpts().CPlusPlus && "No class names in C!");
-
- CXXRecordDecl *CurDecl;
- if (SS && SS->isSet() && !SS->isInvalid()) {
- DeclContext *DC = computeDeclContext(*SS, true);
- CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC);
- } else
- CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
-
- if (CurDecl && CurDecl->getIdentifier())
- return &II == CurDecl->getIdentifier();
- return false;
+ CXXRecordDecl *CurDecl = getCurrentClass(S, SS);
+ return CurDecl && &II == CurDecl->getIdentifier();
}
-/// \brief Determine whether the identifier II is a typo for the name of
+/// Determine whether the identifier II is a typo for the name of
/// the class type currently being defined. If so, update it to the identifier
/// that should have been used.
bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) {
@@ -2107,7 +2117,7 @@ bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) {
return false;
}
-/// \brief Determine whether the given class is a base class of the given
+/// Determine whether the given class is a base class of the given
/// class, including looking at dependent bases.
static bool findCircularInheritance(const CXXRecordDecl *Class,
const CXXRecordDecl *Current) {
@@ -2139,7 +2149,7 @@ static bool findCircularInheritance(const CXXRecordDecl *Class,
return false;
}
-/// \brief Check the validity of a C++ base class specifier.
+/// Check the validity of a C++ base class specifier.
///
/// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics
/// and returns NULL otherwise.
@@ -2233,6 +2243,19 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
CXXRecordDecl *CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
assert(CXXBaseDecl && "Base type is not a C++ type");
+ // Microsoft docs say:
+ // "If a base-class has a code_seg attribute, derived classes must have the
+ // same attribute."
+ const auto *BaseCSA = CXXBaseDecl->getAttr<CodeSegAttr>();
+ const auto *DerivedCSA = Class->getAttr<CodeSegAttr>();
+ if ((DerivedCSA || BaseCSA) &&
+ (!BaseCSA || !DerivedCSA || BaseCSA->getName() != DerivedCSA->getName())) {
+ Diag(Class->getLocation(), diag::err_mismatched_code_seg_base);
+ Diag(CXXBaseDecl->getLocation(), diag::note_base_class_specified_here)
+ << CXXBaseDecl;
+ return nullptr;
+ }
+
// A class which contains a flexible array member is not suitable for use as a
// base class:
// - If the layout determines that a base comes before another base,
@@ -2290,18 +2313,13 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
// We do not support any C++11 attributes on base-specifiers yet.
// Diagnose any attributes we see.
- if (!Attributes.empty()) {
- for (AttributeList *Attr = Attributes.getList(); Attr;
- Attr = Attr->getNext()) {
- if (Attr->isInvalid() ||
- Attr->getKind() == AttributeList::IgnoredAttribute)
- continue;
- Diag(Attr->getLoc(),
- Attr->getKind() == AttributeList::UnknownAttribute
- ? diag::warn_unknown_attribute_ignored
- : diag::err_base_specifier_attribute)
- << Attr->getName();
- }
+ for (const ParsedAttr &AL : Attributes) {
+ if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute)
+ continue;
+ Diag(AL.getLoc(), AL.getKind() == ParsedAttr::UnknownAttribute
+ ? diag::warn_unknown_attribute_ignored
+ : diag::err_base_specifier_attribute)
+ << AL.getName();
}
TypeSourceInfo *TInfo = nullptr;
@@ -2326,7 +2344,7 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
/// locally, there's no need to abstract the small size parameter.
typedef llvm::SmallPtrSet<QualType, 4> IndirectBaseSet;
-/// \brief Recursively add the bases of Type. Don't add Type itself.
+/// Recursively add the bases of Type. Don't add Type itself.
static void
NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set,
const QualType &Type)
@@ -2347,7 +2365,7 @@ NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set,
}
}
-/// \brief Performs the actual work of attaching the given base class
+/// Performs the actual work of attaching the given base class
/// specifiers to a C++ class.
bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
MutableArrayRef<CXXBaseSpecifier *> Bases) {
@@ -2404,7 +2422,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
// The Microsoft extension __interface does not permit bases that
// are not themselves public interfaces.
Diag(KnownBase->getLocStart(), diag::err_invalid_base_in_interface)
- << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getName()
+ << getRecordDiagFromTagKind(RD->getTagKind()) << RD
<< RD->getSourceRange();
Invalid = true;
}
@@ -2417,9 +2435,16 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
// Attach the remaining base class specifiers to the derived class.
Class->setBases(Bases.data(), NumGoodBases);
+ // Check that the only base classes that are duplicate are virtual.
for (unsigned idx = 0; idx < NumGoodBases; ++idx) {
// Check whether this direct base is inaccessible due to ambiguity.
QualType BaseType = Bases[idx]->getType();
+
+ // Skip all dependent types in templates being used as base specifiers.
+ // Checks below assume that the base specifier is a CXXRecord.
+ if (BaseType->isDependentType())
+ continue;
+
CanQualType CanonicalBase = Context.getCanonicalType(BaseType)
.getUnqualifiedType();
@@ -2459,7 +2484,7 @@ void Sema::ActOnBaseSpecifiers(Decl *ClassDecl,
AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases);
}
-/// \brief Determine whether the type \p Derived is a C++ class that is
+/// Determine whether the type \p Derived is a C++ class that is
/// derived from the type \p Base.
bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) {
if (!getLangOpts().CPlusPlus)
@@ -2486,7 +2511,7 @@ bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) {
return DerivedRD->isDerivedFrom(BaseRD);
}
-/// \brief Determine whether the type \p Derived is a C++ class that is
+/// Determine whether the type \p Derived is a C++ class that is
/// derived from the type \p Base.
bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
CXXBasePaths &Paths) {
@@ -2638,7 +2663,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
}
-/// @brief Builds a string representing ambiguous paths from a
+/// Builds a string representing ambiguous paths from a
/// specific derived class to different subobjects of the same base
/// class.
///
@@ -2674,10 +2699,9 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) {
//===----------------------------------------------------------------------===//
/// ActOnAccessSpecifier - Parsed an access specifier followed by a colon.
-bool Sema::ActOnAccessSpecifier(AccessSpecifier Access,
- SourceLocation ASLoc,
+bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc,
SourceLocation ColonLoc,
- AttributeList *Attrs) {
+ const ParsedAttributesView &Attrs) {
assert(Access != AS_none && "Invalid kind for syntactic access specifier!");
AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext,
ASLoc, ColonLoc);
@@ -2764,7 +2788,7 @@ void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D) {
SourceLocation Loc = MD->getLocation();
SourceLocation SpellingLoc = Loc;
if (getSourceManager().isMacroArgExpansion(Loc))
- SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).first;
+ SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).getBegin();
SpellingLoc = getSourceManager().getSpellingLoc(SpellingLoc);
if (SpellingLoc.isValid() && getSourceManager().isInSystemHeader(SpellingLoc))
return;
@@ -2805,10 +2829,13 @@ static bool InitializationHasSideEffects(const FieldDecl &FD) {
return false;
}
-static AttributeList *getMSPropertyAttr(AttributeList *list) {
- for (AttributeList *it = list; it != nullptr; it = it->getNext())
- if (it->isDeclspecPropertyAttribute())
- return it;
+static const ParsedAttr *getMSPropertyAttr(const ParsedAttributesView &list) {
+ ParsedAttributesView::const_iterator Itr =
+ llvm::find_if(list, [](const ParsedAttr &AL) {
+ return AL.isDeclspecPropertyAttribute();
+ });
+ if (Itr != list.end())
+ return &*Itr;
return nullptr;
}
@@ -2855,7 +2882,7 @@ void Sema::CheckShadowInheritedFields(const SourceLocation &Loc,
if (AS_none !=
CXXRecordDecl::MergeAccess(P.Access, BaseField->getAccess())) {
Diag(Loc, diag::warn_shadow_field)
- << FieldName.getAsString() << RD->getName() << Base->getName();
+ << FieldName << RD << Base;
Diag(BaseField->getLocation(), diag::note_shadow_field);
Bases.erase(It);
}
@@ -2887,8 +2914,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
assert(!DS.isFriendSpecified());
bool isFunc = D.isDeclarationOfFunction();
- AttributeList *MSPropertyAttr =
- getMSPropertyAttr(D.getDeclSpec().getAttributes().getList());
+ const ParsedAttr *MSPropertyAttr =
+ getMSPropertyAttr(D.getDeclSpec().getAttributes());
if (cast<CXXRecordDecl>(CurContext)->isInterface()) {
// The Microsoft extension __interface only permits public member functions
@@ -3044,7 +3071,9 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
// int X::member;
// };
if (DeclContext *DC = computeDeclContext(SS, false))
- diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc());
+ diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc(),
+ D.getName().getKind() ==
+ UnqualifiedIdKind::IK_TemplateId);
else
Diag(D.getIdentifierLoc(), diag::err_member_qualification)
<< Name << SS.getRange();
@@ -3054,7 +3083,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
if (MSPropertyAttr) {
Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D,
- BitWidth, InitStyle, AS, MSPropertyAttr);
+ BitWidth, InitStyle, AS, *MSPropertyAttr);
if (!Member)
return nullptr;
isInstField = false;
@@ -3096,14 +3125,38 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
Member->setInvalidDecl();
}
+ NamedDecl *NonTemplateMember = Member;
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
+ NonTemplateMember = FunTmpl->getTemplatedDecl();
+ else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member))
+ NonTemplateMember = VarTmpl->getTemplatedDecl();
+
Member->setAccess(AS);
// If we have declared a member function template or static data member
// template, set the access of the templated declaration as well.
- if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
- FunTmpl->getTemplatedDecl()->setAccess(AS);
- else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member))
- VarTmpl->getTemplatedDecl()->setAccess(AS);
+ if (NonTemplateMember != Member)
+ NonTemplateMember->setAccess(AS);
+
+ // C++ [temp.deduct.guide]p3:
+ // A deduction guide [...] for a member class template [shall be
+ // declared] with the same access [as the template].
+ if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(NonTemplateMember)) {
+ auto *TD = DG->getDeducedTemplate();
+ if (AS != TD->getAccess()) {
+ Diag(DG->getLocStart(), diag::err_deduction_guide_wrong_access);
+ Diag(TD->getLocStart(), diag::note_deduction_guide_template_access)
+ << TD->getAccess();
+ const AccessSpecDecl *LastAccessSpec = nullptr;
+ for (const auto *D : cast<CXXRecordDecl>(CurContext)->decls()) {
+ if (const auto *AccessSpec = dyn_cast<AccessSpecDecl>(D))
+ LastAccessSpec = AccessSpec;
+ }
+ assert(LastAccessSpec && "differing access with no access specifier");
+ Diag(LastAccessSpec->getLocStart(), diag::note_deduction_guide_access)
+ << AS;
+ }
+ }
}
if (VS.isOverrideSpecified())
@@ -3544,7 +3597,7 @@ namespace {
}
} // namespace
-/// \brief Enter a new C++ default initializer scope. After calling this, the
+/// Enter a new C++ default initializer scope. After calling this, the
/// caller must call \ref ActOnFinishCXXInClassMemberInitializer, even if
/// parsing or instantiating the initializer failed.
void Sema::ActOnStartCXXInClassMemberInitializer() {
@@ -3553,7 +3606,7 @@ void Sema::ActOnStartCXXInClassMemberInitializer() {
PushFunctionScope();
}
-/// \brief This is invoked after parsing an in-class initializer for a
+/// This is invoked after parsing an in-class initializer for a
/// non-static C++ class member, and after instantiating an in-class initializer
/// in a class template. Such actions are deferred until the class is complete.
void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
@@ -3581,10 +3634,14 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
ExprResult Init = InitExpr;
if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
- InitializedEntity Entity = InitializedEntity::InitializeMember(FD);
- InitializationKind Kind = FD->getInClassInitStyle() == ICIS_ListInit
- ? InitializationKind::CreateDirectList(InitExpr->getLocStart())
- : InitializationKind::CreateCopy(InitExpr->getLocStart(), InitLoc);
+ InitializedEntity Entity =
+ InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD);
+ InitializationKind Kind =
+ FD->getInClassInitStyle() == ICIS_ListInit
+ ? InitializationKind::CreateDirectList(InitExpr->getLocStart(),
+ InitExpr->getLocStart(),
+ InitExpr->getLocEnd())
+ : InitializationKind::CreateCopy(InitExpr->getLocStart(), InitLoc);
InitializationSequence Seq(*this, Entity, Kind, InitExpr);
Init = Seq.Perform(*this, Entity, Kind, InitExpr);
if (Init.isInvalid()) {
@@ -3607,7 +3664,7 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
FD->setInClassInitializer(InitExpr);
}
-/// \brief Find the direct and/or virtual base specifiers that
+/// Find the direct and/or virtual base specifiers that
/// correspond to the given base type, for use in base initialization
/// within a constructor.
static bool FindBaseInitializer(Sema &SemaRef,
@@ -3651,7 +3708,7 @@ static bool FindBaseInitializer(Sema &SemaRef,
return DirectBaseSpec || VirtualBaseSpec;
}
-/// \brief Handle a C++ member initializer using braced-init-list syntax.
+/// Handle a C++ member initializer using braced-init-list syntax.
MemInitResult
Sema::ActOnMemInitializer(Decl *ConstructorD,
Scope *S,
@@ -3667,7 +3724,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
EllipsisLoc);
}
-/// \brief Handle a C++ member initializer using parentheses syntax.
+/// Handle a C++ member initializer using parentheses syntax.
MemInitResult
Sema::ActOnMemInitializer(Decl *ConstructorD,
Scope *S,
@@ -3710,7 +3767,7 @@ private:
}
-/// \brief Handle a C++ member initializer.
+/// Handle a C++ member initializer.
MemInitResult
Sema::BuildMemInitializer(Decl *ConstructorD,
Scope *S,
@@ -3889,53 +3946,6 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc);
}
-/// Checks a member initializer expression for cases where reference (or
-/// pointer) members are bound to by-value parameters (or their addresses).
-static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member,
- Expr *Init,
- SourceLocation IdLoc) {
- QualType MemberTy = Member->getType();
-
- // We only handle pointers and references currently.
- // FIXME: Would this be relevant for ObjC object pointers? Or block pointers?
- if (!MemberTy->isReferenceType() && !MemberTy->isPointerType())
- return;
-
- const bool IsPointer = MemberTy->isPointerType();
- if (IsPointer) {
- if (const UnaryOperator *Op
- = dyn_cast<UnaryOperator>(Init->IgnoreParenImpCasts())) {
- // The only case we're worried about with pointers requires taking the
- // address.
- if (Op->getOpcode() != UO_AddrOf)
- return;
-
- Init = Op->getSubExpr();
- } else {
- // We only handle address-of expression initializers for pointers.
- return;
- }
- }
-
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) {
- // We only warn when referring to a non-reference parameter declaration.
- const ParmVarDecl *Parameter = dyn_cast<ParmVarDecl>(DRE->getDecl());
- if (!Parameter || Parameter->getType()->isReferenceType())
- return;
-
- S.Diag(Init->getExprLoc(),
- IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
- : diag::warn_bind_ref_member_to_parameter)
- << Member << Parameter << Init->getSourceRange();
- } else {
- // Other initializers are fine.
- return;
- }
-
- S.Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here)
- << (unsigned)IsPointer;
-}
-
MemInitResult
Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
SourceLocation IdLoc) {
@@ -3979,9 +3989,10 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
: InitializedEntity::InitializeMember(IndirectMember,
nullptr);
InitializationKind Kind =
- InitList ? InitializationKind::CreateDirectList(IdLoc)
- : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
- InitRange.getEnd());
+ InitList ? InitializationKind::CreateDirectList(
+ IdLoc, Init->getLocStart(), Init->getLocEnd())
+ : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
+ InitRange.getEnd());
InitializationSequence InitSeq(*this, MemberEntity, Kind, Args);
ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, Args,
@@ -3989,8 +4000,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
if (MemberInit.isInvalid())
return true;
- CheckForDanglingReferenceOrPointer(*this, Member, MemberInit.get(), IdLoc);
-
// C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
@@ -4033,9 +4042,10 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation(
QualType(ClassDecl->getTypeForDecl(), 0));
InitializationKind Kind =
- InitList ? InitializationKind::CreateDirectList(NameLoc)
- : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
- InitRange.getEnd());
+ InitList ? InitializationKind::CreateDirectList(
+ NameLoc, Init->getLocStart(), Init->getLocEnd())
+ : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
+ InitRange.getEnd());
InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args);
ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind,
Args, nullptr);
@@ -4167,9 +4177,9 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
InitializedEntity BaseEntity =
InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec);
InitializationKind Kind =
- InitList ? InitializationKind::CreateDirectList(BaseLoc)
- : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(),
- InitRange.getEnd());
+ InitList ? InitializationKind::CreateDirectList(BaseLoc)
+ : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(),
+ InitRange.getEnd());
InitializationSequence InitSeq(*this, BaseEntity, Kind, Args);
ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, Args, nullptr);
if (BaseInit.isInvalid())
@@ -4321,7 +4331,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
QualType ParamType = Param->getType().getNonReferenceType();
// Suppress copying zero-width bitfields.
- if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0)
+ if (Field->isZeroLengthBitField(SemaRef.Context))
return false;
Expr *MemberExprBase =
@@ -4536,7 +4546,7 @@ struct BaseAndFieldInfo {
return !FieldRD->hasInClassInitializer();
}
- /// \brief Determine whether the given field is, or is within, a union member
+ /// Determine whether the given field is, or is within, a union member
/// that is inactive (because there was an initializer given for a different
/// member of the union, or because the union was not initialized at all).
bool isWithinInactiveUnionMember(FieldDecl *Field,
@@ -4554,7 +4564,7 @@ struct BaseAndFieldInfo {
};
}
-/// \brief Determine whether the given type is an incomplete or zero-lenfgth
+/// Determine whether the given type is an incomplete or zero-lenfgth
/// array type.
static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) {
if (T->isIncompleteArrayType())
@@ -4601,6 +4611,10 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
SemaRef.BuildCXXDefaultInitExpr(Info.Ctor->getLocation(), Field);
if (DIE.isInvalid())
return true;
+
+ auto Entity = InitializedEntity::InitializeMember(Field, nullptr, true);
+ SemaRef.checkInitializerLifetime(Entity, DIE.get());
+
CXXCtorInitializer *Init;
if (Indirect)
Init = new (SemaRef.Context)
@@ -5464,7 +5478,7 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
}
}
-static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) {
+static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
if (!ClassAttr)
return;
@@ -5479,6 +5493,14 @@ static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) {
return;
for (Decl *Member : Class->decls()) {
+ // Defined static variables that are members of an exported base
+ // class must be marked export too.
+ auto *VD = dyn_cast<VarDecl>(Member);
+ if (VD && Member->getAttr<DLLExportAttr>() &&
+ VD->getStorageClass() == SC_Static &&
+ TSK == TSK_ImplicitInstantiation)
+ S.MarkVariableReferenced(VD->getLocation(), VD);
+
auto *MD = dyn_cast<CXXMethodDecl>(Member);
if (!MD)
continue;
@@ -5506,7 +5528,7 @@ static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) {
S.MarkFunctionReferenced(Class->getLocation(), MD);
if (Trap.hasErrorOccurred()) {
S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
- << Class->getName() << !S.getLangOpts().CPlusPlus11;
+ << Class << !S.getLangOpts().CPlusPlus11;
break;
}
@@ -5556,7 +5578,17 @@ static void checkForMultipleExportedDefaultConstructors(Sema &S,
}
}
-/// \brief Check class-level dllimport/dllexport attribute.
+void Sema::checkClassLevelCodeSegAttribute(CXXRecordDecl *Class) {
+ // Mark any compiler-generated routines with the implicit code_seg attribute.
+ for (auto *Method : Class->methods()) {
+ if (Method->isUserProvided())
+ continue;
+ if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true))
+ Method->addAttr(A);
+ }
+}
+
+/// Check class-level dllimport/dllexport attribute.
void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
@@ -5606,6 +5638,13 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
// The class is either imported or exported.
const bool ClassExported = ClassAttr->getKind() == attr::DLLExport;
+ // Check if this was a dllimport attribute propagated from a derived class to
+ // a base class template specialization. We don't apply these attributes to
+ // static data members.
+ const bool PropagatedImport =
+ !ClassExported &&
+ cast<DLLImportAttr>(ClassAttr)->wasPropagatedToBaseTemplate();
+
TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind();
// Ignore explicit dllexport on explicit class template instantiation declarations.
@@ -5657,6 +5696,11 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
}
}
+ // Don't apply dllimport attributes to static data members of class template
+ // instantiations when the attribute is propagated from a derived class.
+ if (VD && PropagatedImport)
+ continue;
+
if (!cast<NamedDecl>(Member)->isExternallyVisible())
continue;
@@ -5665,6 +5709,21 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
NewAttr->setInherited(true);
Member->addAttr(NewAttr);
+
+ if (MD) {
+ // Propagate DLLAttr to friend re-declarations of MD that have already
+ // been constructed.
+ for (FunctionDecl *FD = MD->getMostRecentDecl(); FD;
+ FD = FD->getPreviousDecl()) {
+ if (FD->getFriendObjectKind() == Decl::FOK_None)
+ continue;
+ assert(!getDLLAttr(FD) &&
+ "friend re-decl should not already have a DLLAttr");
+ NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
+ NewAttr->setInherited(true);
+ FD->addAttr(NewAttr);
+ }
+ }
}
}
@@ -5672,7 +5731,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
DelayedDllExportClasses.push_back(Class);
}
-/// \brief Perform propagation of DLL attributes from a derived class to a
+/// Perform propagation of DLL attributes from a derived class to a
/// templated base class for MS compatibility.
void Sema::propagateDLLAttrToBaseClassTemplate(
CXXRecordDecl *Class, Attr *ClassAttr,
@@ -5694,6 +5753,11 @@ void Sema::propagateDLLAttrToBaseClassTemplate(
NewAttr->setInherited(true);
BaseTemplateSpec->addAttr(NewAttr);
+ // If this was an import, mark that we propagated it from a derived class to
+ // a base class template specialization.
+ if (auto *ImportAttr = dyn_cast<DLLImportAttr>(NewAttr))
+ ImportAttr->setPropagatedToBaseTemplate();
+
// If the template is already instantiated, checkDLLAttributeRedeclaration()
// needs to be run again to work see the new attribute. Otherwise this will
// get run whenever the template is instantiated.
@@ -5756,10 +5820,74 @@ static void DefineImplicitSpecialMember(Sema &S, CXXMethodDecl *MD,
/// Determine whether a type is permitted to be passed or returned in
/// registers, per C++ [class.temporary]p3.
-static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
+static bool canPassInRegisters(Sema &S, CXXRecordDecl *D,
+ TargetInfo::CallingConvKind CCK) {
if (D->isDependentType() || D->isInvalidDecl())
return false;
+ // Clang <= 4 used the pre-C++11 rule, which ignores move operations.
+ // The PS4 platform ABI follows the behavior of Clang 3.2.
+ if (CCK == TargetInfo::CCK_ClangABI4OrPS4)
+ return !D->hasNonTrivialDestructorForCall() &&
+ !D->hasNonTrivialCopyConstructorForCall();
+
+ if (CCK == TargetInfo::CCK_MicrosoftWin64) {
+ bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false;
+ bool DtorIsTrivialForCall = false;
+
+ // If a class has at least one non-deleted, trivial copy constructor, it
+ // is passed according to the C ABI. Otherwise, it is passed indirectly.
+ //
+ // Note: This permits classes with non-trivial copy or move ctors to be
+ // passed in registers, so long as they *also* have a trivial copy ctor,
+ // which is non-conforming.
+ if (D->needsImplicitCopyConstructor()) {
+ if (!D->defaultedCopyConstructorIsDeleted()) {
+ if (D->hasTrivialCopyConstructor())
+ CopyCtorIsTrivial = true;
+ if (D->hasTrivialCopyConstructorForCall())
+ CopyCtorIsTrivialForCall = true;
+ }
+ } else {
+ for (const CXXConstructorDecl *CD : D->ctors()) {
+ if (CD->isCopyConstructor() && !CD->isDeleted()) {
+ if (CD->isTrivial())
+ CopyCtorIsTrivial = true;
+ if (CD->isTrivialForCall())
+ CopyCtorIsTrivialForCall = true;
+ }
+ }
+ }
+
+ if (D->needsImplicitDestructor()) {
+ if (!D->defaultedDestructorIsDeleted() &&
+ D->hasTrivialDestructorForCall())
+ DtorIsTrivialForCall = true;
+ } else if (const auto *DD = D->getDestructor()) {
+ if (!DD->isDeleted() && DD->isTrivialForCall())
+ DtorIsTrivialForCall = true;
+ }
+
+ // If the copy ctor and dtor are both trivial-for-calls, pass direct.
+ if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall)
+ return true;
+
+ // If a class has a destructor, we'd really like to pass it indirectly
+ // because it allows us to elide copies. Unfortunately, MSVC makes that
+ // impossible for small types, which it will pass in a single register or
+ // stack slot. Most objects with dtors are large-ish, so handle that early.
+ // We can't call out all large objects as being indirect because there are
+ // multiple x64 calling conventions and the C++ ABI code shouldn't dictate
+ // how we pass large POD types.
+
+ // Note: This permits small classes with nontrivial destructors to be
+ // passed in registers, which is non-conforming.
+ if (CopyCtorIsTrivial &&
+ S.getASTContext().getTypeSize(D->getTypeForDecl()) <= 64)
+ return true;
+ return false;
+ }
+
// Per C++ [class.temporary]p3, the relevant condition is:
// each copy constructor, move constructor, and destructor of X is
// either trivial or deleted, and X has at least one non-deleted copy
@@ -5768,20 +5896,20 @@ static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
if (D->needsImplicitCopyConstructor() &&
!D->defaultedCopyConstructorIsDeleted()) {
- if (!D->hasTrivialCopyConstructor())
+ if (!D->hasTrivialCopyConstructorForCall())
return false;
HasNonDeletedCopyOrMove = true;
}
if (S.getLangOpts().CPlusPlus11 && D->needsImplicitMoveConstructor() &&
!D->defaultedMoveConstructorIsDeleted()) {
- if (!D->hasTrivialMoveConstructor())
+ if (!D->hasTrivialMoveConstructorForCall())
return false;
HasNonDeletedCopyOrMove = true;
}
if (D->needsImplicitDestructor() && !D->defaultedDestructorIsDeleted() &&
- !D->hasTrivialDestructor())
+ !D->hasTrivialDestructorForCall())
return false;
for (const CXXMethodDecl *MD : D->methods()) {
@@ -5794,14 +5922,14 @@ static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
else if (!isa<CXXDestructorDecl>(MD))
continue;
- if (!MD->isTrivial())
+ if (!MD->isTrivialForCall())
return false;
}
return HasNonDeletedCopyOrMove;
}
-/// \brief Perform semantic checks on a class definition that has been
+/// Perform semantic checks on a class definition that has been
/// completing, introducing implicitly-declared members, checking for
/// abstract types, etc.
void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
@@ -5851,10 +5979,11 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
DeclContext::lookup_result R = Record->lookup(Record->getDeclName());
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
++I) {
- NamedDecl *D = *I;
- if ((isa<FieldDecl>(D) && Record->hasUserDeclaredConstructor()) ||
+ NamedDecl *D = (*I)->getUnderlyingDecl();
+ if (((isa<FieldDecl>(D) || isa<UnresolvedUsingValueDecl>(D)) &&
+ Record->hasUserDeclaredConstructor()) ||
isa<IndirectFieldDecl>(D)) {
- Diag(D->getLocation(), diag::err_member_name_of_class)
+ Diag((*I)->getLocation(), diag::err_member_name_of_class)
<< D->getDeclName();
break;
}
@@ -5878,6 +6007,17 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
}
+ // See if trivial_abi has to be dropped.
+ if (Record->hasAttr<TrivialABIAttr>())
+ checkIllFormedTrivialABIStruct(*Record);
+
+ // Set HasTrivialSpecialMemberForCall if the record has attribute
+ // "trivial_abi".
+ bool HasTrivialABI = Record->hasAttr<TrivialABIAttr>();
+
+ if (HasTrivialABI)
+ Record->setHasTrivialSpecialMemberForCall();
+
bool HasMethodWithOverrideControl = false,
HasOverridingMethodWithoutOverrideControl = false;
if (!Record->isDependentType()) {
@@ -5900,12 +6040,23 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
if (!M->isImplicit() && !M->isUserProvided()) {
if (CSM != CXXInvalid) {
M->setTrivial(SpecialMemberIsTrivial(M, CSM));
-
// Inform the class that we've finished declaring this member.
Record->finishedDefaultedOrDeletedMember(M);
+ M->setTrivialForCall(
+ HasTrivialABI ||
+ SpecialMemberIsTrivial(M, CSM, TAH_ConsiderTrivialABI));
+ Record->setTrivialForCallFlags(M);
}
}
+ // Set triviality for the purpose of calls if this is a user-provided
+ // copy/move constructor or destructor.
+ if ((CSM == CXXCopyConstructor || CSM == CXXMoveConstructor ||
+ CSM == CXXDestructor) && M->isUserProvided()) {
+ M->setTrivialForCall(HasTrivialABI);
+ Record->setTrivialForCallFlags(M);
+ }
+
if (!M->isInvalidDecl() && M->isExplicitlyDefaulted() &&
M->hasAttr<DLLExportAttr>()) {
if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
@@ -5945,8 +6096,35 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
checkClassLevelDLLAttribute(Record);
+ checkClassLevelCodeSegAttribute(Record);
+
+ bool ClangABICompat4 =
+ Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver4;
+ TargetInfo::CallingConvKind CCK =
+ Context.getTargetInfo().getCallingConvKind(ClangABICompat4);
+ bool CanPass = canPassInRegisters(*this, Record, CCK);
+
+ // Do not change ArgPassingRestrictions if it has already been set to
+ // APK_CanNeverPassInRegs.
+ if (Record->getArgPassingRestrictions() != RecordDecl::APK_CanNeverPassInRegs)
+ Record->setArgPassingRestrictions(CanPass
+ ? RecordDecl::APK_CanPassInRegs
+ : RecordDecl::APK_CannotPassInRegs);
- Record->setCanPassInRegisters(computeCanPassInRegisters(*this, Record));
+ // If canPassInRegisters returns true despite the record having a non-trivial
+ // destructor, the record is destructed in the callee. This happens only when
+ // the record or one of its subobjects has a field annotated with trivial_abi
+ // or a field qualified with ObjC __strong/__weak.
+ if (Context.getTargetInfo().getCXXABI().areArgsDestroyedLeftToRightInCallee())
+ Record->setParamDestroyedInCallee(true);
+ else if (Record->hasNonTrivialDestructor())
+ Record->setParamDestroyedInCallee(CanPass);
+
+ if (getLangOpts().ForceEmitVTables) {
+ // If we want to emit all the vtables, we need to mark it as used. This
+ // is especially required for cases like vtable assumption loads.
+ MarkVTableUsed(Record->getInnerLocStart(), Record);
+ }
}
/// Look up the special member function that would be called by a special
@@ -7017,9 +7195,14 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
///
/// If \p Selected is not \c NULL, \c *Selected will be filled in with the
/// member that was most likely to be intended to be trivial, if any.
+///
+/// If \p ForCall is true, look at CXXRecord::HasTrivialSpecialMembersForCall to
+/// determine whether the special member is trivial.
static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
Sema::CXXSpecialMember CSM, unsigned Quals,
- bool ConstRHS, CXXMethodDecl **Selected) {
+ bool ConstRHS,
+ Sema::TrivialABIHandling TAH,
+ CXXMethodDecl **Selected) {
if (Selected)
*Selected = nullptr;
@@ -7060,7 +7243,9 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
// C++11 [class.dtor]p5:
// A destructor is trivial if:
// - all the direct [subobjects] have trivial destructors
- if (RD->hasTrivialDestructor())
+ if (RD->hasTrivialDestructor() ||
+ (TAH == Sema::TAH_ConsiderTrivialABI &&
+ RD->hasTrivialDestructorForCall()))
return true;
if (Selected) {
@@ -7075,7 +7260,9 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
// C++11 [class.copy]p12:
// A copy constructor is trivial if:
// - the constructor selected to copy each direct [subobject] is trivial
- if (RD->hasTrivialCopyConstructor()) {
+ if (RD->hasTrivialCopyConstructor() ||
+ (TAH == Sema::TAH_ConsiderTrivialABI &&
+ RD->hasTrivialCopyConstructorForCall())) {
if (Quals == Qualifiers::Const)
// We must either select the trivial copy constructor or reach an
// ambiguity; no need to actually perform overload resolution.
@@ -7128,6 +7315,10 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
// not supposed to!
if (Selected)
*Selected = SMOR.getMethod();
+
+ if (TAH == Sema::TAH_ConsiderTrivialABI &&
+ (CSM == Sema::CXXCopyConstructor || CSM == Sema::CXXMoveConstructor))
+ return SMOR.getMethod()->isTrivialForCall();
return SMOR.getMethod()->isTrivial();
}
@@ -7166,14 +7357,14 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
QualType SubType, bool ConstRHS,
Sema::CXXSpecialMember CSM,
TrivialSubobjectKind Kind,
- bool Diagnose) {
+ Sema::TrivialABIHandling TAH, bool Diagnose) {
CXXRecordDecl *SubRD = SubType->getAsCXXRecordDecl();
if (!SubRD)
return true;
CXXMethodDecl *Selected;
if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(),
- ConstRHS, Diagnose ? &Selected : nullptr))
+ ConstRHS, TAH, Diagnose ? &Selected : nullptr))
return true;
if (Diagnose) {
@@ -7203,7 +7394,8 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
<< Kind << SubType.getUnqualifiedType() << CSM;
// Explain why the defaulted or deleted special member isn't trivial.
- S.SpecialMemberIsTrivial(Selected, CSM, Diagnose);
+ S.SpecialMemberIsTrivial(Selected, CSM, Sema::TAH_IgnoreTrivialABI,
+ Diagnose);
}
}
@@ -7214,7 +7406,9 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
/// trivial.
static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
Sema::CXXSpecialMember CSM,
- bool ConstArg, bool Diagnose) {
+ bool ConstArg,
+ Sema::TrivialABIHandling TAH,
+ bool Diagnose) {
for (const auto *FI : RD->fields()) {
if (FI->isInvalidDecl() || FI->isUnnamedBitfield())
continue;
@@ -7224,7 +7418,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
// Pretend anonymous struct or union members are members of this class.
if (FI->isAnonymousStructOrUnion()) {
if (!checkTrivialClassMembers(S, FieldType->getAsCXXRecordDecl(),
- CSM, ConstArg, Diagnose))
+ CSM, ConstArg, TAH, Diagnose))
return false;
continue;
}
@@ -7252,7 +7446,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
bool ConstRHS = ConstArg && !FI->isMutable();
if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, ConstRHS,
- CSM, TSK_Field, Diagnose))
+ CSM, TSK_Field, TAH, Diagnose))
return false;
}
@@ -7266,14 +7460,15 @@ void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) {
bool ConstArg = (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment);
checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, ConstArg, CSM,
- TSK_CompleteObject, /*Diagnose*/true);
+ TSK_CompleteObject, TAH_IgnoreTrivialABI,
+ /*Diagnose*/true);
}
/// Determine whether a defaulted or deleted special member function is trivial,
/// as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12,
/// C++11 [class.copy]p25, and C++11 [class.dtor]p5.
bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
- bool Diagnose) {
+ TrivialABIHandling TAH, bool Diagnose) {
assert(!MD->isUserProvided() && CSM != CXXInvalid && "not special enough");
CXXRecordDecl *RD = MD->getParent();
@@ -7350,7 +7545,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
// destructors]
for (const auto &BI : RD->bases())
if (!checkTrivialSubobjectCall(*this, BI.getLocStart(), BI.getType(),
- ConstArg, CSM, TSK_BaseClass, Diagnose))
+ ConstArg, CSM, TSK_BaseClass, TAH, Diagnose))
return false;
// C++11 [class.ctor]p5, C++11 [class.dtor]p5:
@@ -7365,7 +7560,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
// -- for all of the non-static data members of its class that are of class
// type (or array thereof), each such class has a trivial [default
// constructor or destructor]
- if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, Diagnose))
+ if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, TAH, Diagnose))
return false;
// C++11 [class.dtor]p5:
@@ -7477,7 +7672,7 @@ public:
};
} // end anonymous namespace
-/// \brief Add the most overriden methods from MD to Methods
+/// Add the most overriden methods from MD to Methods
static void AddMostOverridenMethods(const CXXMethodDecl *MD,
llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) {
if (MD->size_overridden_methods() == 0)
@@ -7487,7 +7682,7 @@ static void AddMostOverridenMethods(const CXXMethodDecl *MD,
AddMostOverridenMethods(O, Methods);
}
-/// \brief Check if a method overloads virtual methods in a base class without
+/// Check if a method overloads virtual methods in a base class without
/// overriding any.
void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD,
SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) {
@@ -7528,7 +7723,7 @@ void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD,
}
}
-/// \brief Diagnose methods which overload virtual methods in a base class
+/// Diagnose methods which overload virtual methods in a base class
/// without overriding any.
void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) {
if (MD->isInvalidDecl())
@@ -7547,22 +7742,64 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) {
}
}
-void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
- Decl *TagDecl,
- SourceLocation LBrac,
- SourceLocation RBrac,
- AttributeList *AttrList) {
+void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) {
+ auto PrintDiagAndRemoveAttr = [&]() {
+ // No diagnostics if this is a template instantiation.
+ if (!isTemplateInstantiation(RD.getTemplateSpecializationKind()))
+ Diag(RD.getAttr<TrivialABIAttr>()->getLocation(),
+ diag::ext_cannot_use_trivial_abi) << &RD;
+ RD.dropAttr<TrivialABIAttr>();
+ };
+
+ // Ill-formed if the struct has virtual functions.
+ if (RD.isPolymorphic()) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+
+ for (const auto &B : RD.bases()) {
+ // Ill-formed if the base class is non-trivial for the purpose of calls or a
+ // virtual base.
+ if ((!B.getType()->isDependentType() &&
+ !B.getType()->getAsCXXRecordDecl()->canPassInRegisters()) ||
+ B.isVirtual()) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+ }
+
+ for (const auto *FD : RD.fields()) {
+ // Ill-formed if the field is an ObjectiveC pointer or of a type that is
+ // non-trivial for the purpose of calls.
+ QualType FT = FD->getType();
+ if (FT.getObjCLifetime() == Qualifiers::OCL_Weak) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+
+ if (const auto *RT = FT->getBaseElementTypeUnsafe()->getAs<RecordType>())
+ if (!RT->isDependentType() &&
+ !cast<CXXRecordDecl>(RT->getDecl())->canPassInRegisters()) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+ }
+}
+
+void Sema::ActOnFinishCXXMemberSpecification(
+ Scope *S, SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac,
+ SourceLocation RBrac, const ParsedAttributesView &AttrList) {
if (!TagDecl)
return;
AdjustDeclIfTemplate(TagDecl);
- for (const AttributeList* l = AttrList; l; l = l->getNext()) {
- if (l->getKind() != AttributeList::AT_Visibility)
+ for (const ParsedAttr &AL : AttrList) {
+ if (AL.getKind() != ParsedAttr::AT_Visibility)
continue;
- l->setInvalid();
- Diag(l->getLoc(), diag::warn_attribute_after_definition_ignored) <<
- l->getName();
+ AL.setInvalid();
+ Diag(AL.getLoc(), diag::warn_attribute_after_definition_ignored)
+ << AL.getName();
}
ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef(
@@ -7570,7 +7807,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
reinterpret_cast<Decl**>(FieldCollector->getCurFields()),
FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList);
- CheckCompletedCXXClass(dyn_cast_or_null<CXXRecordDecl>(TagDecl));
+ CheckCompletedCXXClass(cast<CXXRecordDecl>(TagDecl));
}
/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
@@ -8108,7 +8345,8 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
QualType ConvType =
GetTypeFromParser(D.getName().ConversionFunctionId, &ConvTSI);
- if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
+ const DeclSpec &DS = D.getDeclSpec();
+ if (DS.hasTypeSpecifier() && !D.isInvalidType()) {
// Conversion functions don't have return types, but the parser will
// happily parse something like:
//
@@ -8118,9 +8356,18 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
//
// The return type will be changed later anyway.
Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type)
- << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
+ << SourceRange(DS.getTypeSpecTypeLoc())
<< SourceRange(D.getIdentifierLoc());
D.setInvalidType();
+ } else if (DS.getTypeQualifiers() && !D.isInvalidType()) {
+ // It's also plausible that the user writes type qualifiers in the wrong
+ // place, such as:
+ // struct S { const operator int(); };
+ // FIXME: we could provide a fixit to move the qualifiers onto the
+ // conversion type.
+ Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl)
+ << SourceRange(D.getIdentifierLoc()) << 0;
+ D.setInvalidType();
}
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
@@ -8233,12 +8480,12 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
R = Context.getFunctionType(ConvType, None, Proto->getExtProtoInfo());
// C++0x explicit conversion operators.
- if (D.getDeclSpec().isExplicitSpecified())
- Diag(D.getDeclSpec().getExplicitSpecLoc(),
- getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_explicit_conversion_functions :
- diag::ext_explicit_conversion_functions)
- << SourceRange(D.getDeclSpec().getExplicitSpecLoc());
+ if (DS.isExplicitSpecified())
+ Diag(DS.getExplicitSpecLoc(),
+ getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_explicit_conversion_functions
+ : diag::ext_explicit_conversion_functions)
+ << SourceRange(DS.getExplicitSpecLoc());
}
/// ActOnConversionDeclarator - Called by ActOnDeclarator to complete
@@ -8437,7 +8684,7 @@ void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
// Namespace Handling
//===----------------------------------------------------------------------===//
-/// \brief Diagnose a mismatch in 'inline' qualifiers when a namespace is
+/// Diagnose a mismatch in 'inline' qualifiers when a namespace is
/// reopened.
static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc,
SourceLocation Loc,
@@ -8479,14 +8726,10 @@ static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc,
/// ActOnStartNamespaceDef - This is called at the start of a namespace
/// definition.
-Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
- SourceLocation InlineLoc,
- SourceLocation NamespaceLoc,
- SourceLocation IdentLoc,
- IdentifierInfo *II,
- SourceLocation LBrace,
- AttributeList *AttrList,
- UsingDirectiveDecl *&UD) {
+Decl *Sema::ActOnStartNamespaceDef(
+ Scope *NamespcScope, SourceLocation InlineLoc, SourceLocation NamespaceLoc,
+ SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace,
+ const ParsedAttributesView &AttrList, UsingDirectiveDecl *&UD) {
SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc;
// For anonymous namespace, take the location of the left brace.
SourceLocation Loc = II ? IdentLoc : LBrace;
@@ -8673,7 +8916,137 @@ NamespaceDecl *Sema::lookupStdExperimentalNamespace() {
return StdExperimentalNamespaceCache;
}
-/// \brief Retrieve the special "std" namespace, which may require us to
+namespace {
+
+enum UnsupportedSTLSelect {
+ USS_InvalidMember,
+ USS_MissingMember,
+ USS_NonTrivial,
+ USS_Other
+};
+
+struct InvalidSTLDiagnoser {
+ Sema &S;
+ SourceLocation Loc;
+ QualType TyForDiags;
+
+ QualType operator()(UnsupportedSTLSelect Sel = USS_Other, StringRef Name = "",
+ const VarDecl *VD = nullptr) {
+ {
+ auto D = S.Diag(Loc, diag::err_std_compare_type_not_supported)
+ << TyForDiags << ((int)Sel);
+ if (Sel == USS_InvalidMember || Sel == USS_MissingMember) {
+ assert(!Name.empty());
+ D << Name;
+ }
+ }
+ if (Sel == USS_InvalidMember) {
+ S.Diag(VD->getLocation(), diag::note_var_declared_here)
+ << VD << VD->getSourceRange();
+ }
+ return QualType();
+ }
+};
+} // namespace
+
+QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind,
+ SourceLocation Loc) {
+ assert(getLangOpts().CPlusPlus &&
+ "Looking for comparison category type outside of C++.");
+
+ // Check if we've already successfully checked the comparison category type
+ // before. If so, skip checking it again.
+ ComparisonCategoryInfo *Info = Context.CompCategories.lookupInfo(Kind);
+ if (Info && FullyCheckedComparisonCategories[static_cast<unsigned>(Kind)])
+ return Info->getType();
+
+ // If lookup failed
+ if (!Info) {
+ std::string NameForDiags = "std::";
+ NameForDiags += ComparisonCategories::getCategoryString(Kind);
+ Diag(Loc, diag::err_implied_comparison_category_type_not_found)
+ << NameForDiags;
+ return QualType();
+ }
+
+ assert(Info->Kind == Kind);
+ assert(Info->Record);
+
+ // Update the Record decl in case we encountered a forward declaration on our
+ // first pass. FIXME: This is a bit of a hack.
+ if (Info->Record->hasDefinition())
+ Info->Record = Info->Record->getDefinition();
+
+ // Use an elaborated type for diagnostics which has a name containing the
+ // prepended 'std' namespace but not any inline namespace names.
+ QualType TyForDiags = [&]() {
+ auto *NNS =
+ NestedNameSpecifier::Create(Context, nullptr, getStdNamespace());
+ return Context.getElaboratedType(ETK_None, NNS, Info->getType());
+ }();
+
+ if (RequireCompleteType(Loc, TyForDiags, diag::err_incomplete_type))
+ return QualType();
+
+ InvalidSTLDiagnoser UnsupportedSTLError{*this, Loc, TyForDiags};
+
+ if (!Info->Record->isTriviallyCopyable())
+ return UnsupportedSTLError(USS_NonTrivial);
+
+ for (const CXXBaseSpecifier &BaseSpec : Info->Record->bases()) {
+ CXXRecordDecl *Base = BaseSpec.getType()->getAsCXXRecordDecl();
+ // Tolerate empty base classes.
+ if (Base->isEmpty())
+ continue;
+ // Reject STL implementations which have at least one non-empty base.
+ return UnsupportedSTLError();
+ }
+
+ // Check that the STL has implemented the types using a single integer field.
+ // This expectation allows better codegen for builtin operators. We require:
+ // (1) The class has exactly one field.
+ // (2) The field is an integral or enumeration type.
+ auto FIt = Info->Record->field_begin(), FEnd = Info->Record->field_end();
+ if (std::distance(FIt, FEnd) != 1 ||
+ !FIt->getType()->isIntegralOrEnumerationType()) {
+ return UnsupportedSTLError();
+ }
+
+ // Build each of the require values and store them in Info.
+ for (ComparisonCategoryResult CCR :
+ ComparisonCategories::getPossibleResultsForType(Kind)) {
+ StringRef MemName = ComparisonCategories::getResultString(CCR);
+ ComparisonCategoryInfo::ValueInfo *ValInfo = Info->lookupValueInfo(CCR);
+
+ if (!ValInfo)
+ return UnsupportedSTLError(USS_MissingMember, MemName);
+
+ VarDecl *VD = ValInfo->VD;
+ assert(VD && "should not be null!");
+
+ // Attempt to diagnose reasons why the STL definition of this type
+ // might be foobar, including it failing to be a constant expression.
+ // TODO Handle more ways the lookup or result can be invalid.
+ if (!VD->isStaticDataMember() || !VD->isConstexpr() || !VD->hasInit() ||
+ !VD->checkInitIsICE())
+ return UnsupportedSTLError(USS_InvalidMember, MemName, VD);
+
+ // Attempt to evaluate the var decl as a constant expression and extract
+ // the value of its first field as a ICE. If this fails, the STL
+ // implementation is not supported.
+ if (!ValInfo->hasValidIntValue())
+ return UnsupportedSTLError();
+
+ MarkVariableReferenced(Loc, VD);
+ }
+
+ // We've successfully built the required types and expressions. Update
+ // the cache and return the newly cached value.
+ FullyCheckedComparisonCategories[static_cast<unsigned>(Kind)] = true;
+ return Info->getType();
+}
+
+/// Retrieve the special "std" namespace, which may require us to
/// implicitly define the namespace.
NamespaceDecl *Sema::getOrCreateStdNamespace() {
if (!StdNamespace) {
@@ -8816,7 +9189,7 @@ bool Sema::isInitListConstructor(const FunctionDecl *Ctor) {
return isStdInitializerList(ArgType, nullptr);
}
-/// \brief Determine whether a using statement is in a context where it will be
+/// Determine whether a using statement is in a context where it will be
/// apply in all contexts.
static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) {
switch (CurContext->getDeclKind()) {
@@ -8871,13 +9244,11 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
return false;
}
-Decl *Sema::ActOnUsingDirective(Scope *S,
- SourceLocation UsingLoc,
- SourceLocation NamespcLoc,
- CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *NamespcName,
- AttributeList *AttrList) {
+Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc,
+ SourceLocation NamespcLoc, CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *NamespcName,
+ const ParsedAttributesView &AttrList) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
assert(NamespcName && "Invalid NamespcName.");
assert(IdentLoc.isValid() && "Invalid NamespceName location.");
@@ -8932,7 +9303,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
// Find enclosing context containing both using-directive and
// nominated namespace.
- DeclContext *CommonAncestor = cast<DeclContext>(NS);
+ DeclContext *CommonAncestor = NS;
while (CommonAncestor && !CommonAncestor->Encloses(CurContext))
CommonAncestor = CommonAncestor->getParent();
@@ -8969,15 +9340,12 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
S->PushUsingDirective(UDir);
}
-
-Decl *Sema::ActOnUsingDeclaration(Scope *S,
- AccessSpecifier AS,
+Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS,
SourceLocation UsingLoc,
- SourceLocation TypenameLoc,
- CXXScopeSpec &SS,
+ SourceLocation TypenameLoc, CXXScopeSpec &SS,
UnqualifiedId &Name,
SourceLocation EllipsisLoc,
- AttributeList *AttrList) {
+ const ParsedAttributesView &AttrList) {
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
if (SS.isEmpty()) {
@@ -8986,15 +9354,15 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
}
switch (Name.getKind()) {
- case UnqualifiedId::IK_ImplicitSelfParam:
- case UnqualifiedId::IK_Identifier:
- case UnqualifiedId::IK_OperatorFunctionId:
- case UnqualifiedId::IK_LiteralOperatorId:
- case UnqualifiedId::IK_ConversionFunctionId:
+ case UnqualifiedIdKind::IK_ImplicitSelfParam:
+ case UnqualifiedIdKind::IK_Identifier:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_ConversionFunctionId:
break;
- case UnqualifiedId::IK_ConstructorName:
- case UnqualifiedId::IK_ConstructorTemplateId:
+ case UnqualifiedIdKind::IK_ConstructorName:
+ case UnqualifiedIdKind::IK_ConstructorTemplateId:
// C++11 inheriting constructors.
Diag(Name.getLocStart(),
getLangOpts().CPlusPlus11 ?
@@ -9006,17 +9374,17 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
return nullptr;
- case UnqualifiedId::IK_DestructorName:
+ case UnqualifiedIdKind::IK_DestructorName:
Diag(Name.getLocStart(), diag::err_using_decl_destructor)
<< SS.getRange();
return nullptr;
- case UnqualifiedId::IK_TemplateId:
+ case UnqualifiedIdKind::IK_TemplateId:
Diag(Name.getLocStart(), diag::err_using_decl_template_id)
<< SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
return nullptr;
- case UnqualifiedId::IK_DeductionGuideName:
+ case UnqualifiedIdKind::IK_DeductionGuideName:
llvm_unreachable("cannot parse qualified deduction guide name");
}
@@ -9056,7 +9424,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
return UD;
}
-/// \brief Determine whether a using declaration considers the given
+/// Determine whether a using declaration considers the given
/// declarations as "equivalent", e.g., if they are redeclarations of
/// the same entity or are both typedefs of the same type.
static bool
@@ -9149,6 +9517,19 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
if (isa<UsingDecl>(D) || isa<UsingPackDecl>(D))
continue;
+ if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
+ // C++ [class.mem]p19:
+ // If T is the name of a class, then [every named member other than
+ // a non-static data member] shall have a name different from T
+ if (RD->isInjectedClassName() && !isa<FieldDecl>(Target) &&
+ !isa<IndirectFieldDecl>(Target) &&
+ !isa<UnresolvedUsingValueDecl>(Target) &&
+ DiagnoseClassNameShadow(
+ CurContext,
+ DeclarationNameInfo(Using->getDeclName(), Using->getLocation())))
+ return true;
+ }
+
if (IsEquivalentForUsingDecl(Context, D, Target)) {
if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I))
PrevShadow = Shadow;
@@ -9421,15 +9802,11 @@ private:
/// \param IsInstantiation - Whether this call arises from an
/// instantiation of an unresolved using declaration. We treat
/// the lookup differently for these declarations.
-NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
- SourceLocation UsingLoc,
- bool HasTypenameKeyword,
- SourceLocation TypenameLoc,
- CXXScopeSpec &SS,
- DeclarationNameInfo NameInfo,
- SourceLocation EllipsisLoc,
- AttributeList *AttrList,
- bool IsInstantiation) {
+NamedDecl *Sema::BuildUsingDeclaration(
+ Scope *S, AccessSpecifier AS, SourceLocation UsingLoc,
+ bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS,
+ DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc,
+ const ParsedAttributesView &AttrList, bool IsInstantiation) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
SourceLocation IdentLoc = NameInfo.getLoc();
assert(IdentLoc.isValid() && "Invalid TargetName location.");
@@ -9995,14 +10372,11 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
return true;
}
-Decl *Sema::ActOnAliasDeclaration(Scope *S,
- AccessSpecifier AS,
+Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS,
MultiTemplateParamsArg TemplateParamLists,
- SourceLocation UsingLoc,
- UnqualifiedId &Name,
- AttributeList *AttrList,
- TypeResult Type,
- Decl *DeclFromDeclSpec) {
+ SourceLocation UsingLoc, UnqualifiedId &Name,
+ const ParsedAttributesView &AttrList,
+ TypeResult Type, Decl *DeclFromDeclSpec) {
// Skip up to the relevant declaration scope.
while (S->isTemplateParamScope())
S = S->getParent();
@@ -10040,7 +10414,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
Previous.clear();
}
- assert(Name.Kind == UnqualifiedId::IK_Identifier &&
+ assert(Name.Kind == UnqualifiedIdKind::IK_Identifier &&
"name in alias declaration must be an identifier");
TypeAliasDecl *NewTD = TypeAliasDecl::Create(Context, CurContext, UsingLoc,
Name.StartLocation,
@@ -10378,7 +10752,7 @@ struct DeclaringSpecialMember {
}
}
- /// \brief Are we already trying to declare this special member?
+ /// Are we already trying to declare this special member?
bool isAlreadyBeingDeclared() const {
return WasAlreadyBeingDeclared;
}
@@ -10720,6 +11094,8 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
// We don't need to use SpecialMemberIsTrivial here; triviality for
// destructors is easy to compute.
Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
+ Destructor->setTrivialForCall(ClassDecl->hasAttr<TrivialABIAttr>() ||
+ ClassDecl->hasTrivialDestructorForCall());
// Note that we have declared this destructor.
++ASTContext::NumImplicitDestructorsDeclared;
@@ -10784,7 +11160,7 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
}
}
-/// \brief Perform any semantic analysis which needs to be delayed until all
+/// Perform any semantic analysis which needs to be delayed until all
/// pending class member declarations have been parsed.
void Sema::ActOnFinishCXXMemberDecls() {
// If the context is an invalid C++ class, just suppress these checks.
@@ -10804,12 +11180,12 @@ void Sema::ActOnFinishCXXNonNestedClass(Decl *D) {
void Sema::referenceDLLExportedClassMethods() {
if (!DelayedDllExportClasses.empty()) {
- // Calling ReferenceDllExportedMethods might cause the current function to
+ // Calling ReferenceDllExportedMembers might cause the current function to
// be called again, so use a local copy of DelayedDllExportClasses.
SmallVector<CXXRecordDecl *, 4> WorkList;
std::swap(DelayedDllExportClasses, WorkList);
for (CXXRecordDecl *Class : WorkList)
- ReferenceDllExportedMethods(*this, Class);
+ ReferenceDllExportedMembers(*this, Class);
}
}
@@ -10843,7 +11219,7 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
}
namespace {
-/// \brief An abstract base class for all helper classes used in building the
+/// An abstract base class for all helper classes used in building the
// copy/move operators. These classes serve as factory functions and help us
// avoid using the same Expr* in the AST twice.
class ExprBuilder {
@@ -10990,11 +11366,11 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
Expr *From = FromB.build(S, Loc);
From = new (S.Context) UnaryOperator(From, UO_AddrOf,
S.Context.getPointerType(From->getType()),
- VK_RValue, OK_Ordinary, Loc);
+ VK_RValue, OK_Ordinary, Loc, false);
Expr *To = ToB.build(S, Loc);
To = new (S.Context) UnaryOperator(To, UO_AddrOf,
S.Context.getPointerType(To->getType()),
- VK_RValue, OK_Ordinary, Loc);
+ VK_RValue, OK_Ordinary, Loc, false);
const Type *E = T->getBaseElementTypeUnsafe();
bool NeedsCollectableMemCpy =
@@ -11028,7 +11404,7 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
return Call.getAs<Stmt>();
}
-/// \brief Builds a statement that copies/moves the given entity from \p From to
+/// Builds a statement that copies/moves the given entity from \p From to
/// \c To.
///
/// This routine is used to copy/move the members of a class with an
@@ -11233,10 +11609,12 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
BO_NE, S.Context.BoolTy,
VK_RValue, OK_Ordinary, Loc, FPOptions());
- // Create the pre-increment of the iteration variable.
- Expr *Increment
- = new (S.Context) UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc,
- SizeType, VK_LValue, OK_Ordinary, Loc);
+ // Create the pre-increment of the iteration variable. We can determine
+ // whether the increment will overflow based on the value of the array
+ // bound.
+ Expr *Increment = new (S.Context)
+ UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc, SizeType,
+ VK_LValue, OK_Ordinary, Loc, Upper.isMaxValue());
// Construct the loop that copies all elements of this array.
return S.ActOnForStmt(
@@ -11525,7 +11903,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
}
// Suppress assigning zero-width bitfields.
- if (Field->isBitField() && Field->getBitWidthValue(Context) == 0)
+ if (Field->isZeroLengthBitField(Context))
continue;
QualType FieldType = Field->getType().getNonReferenceType();
@@ -11892,7 +12270,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
}
// Suppress assigning zero-width bitfields.
- if (Field->isBitField() && Field->getBitWidthValue(Context) == 0)
+ if (Field->isZeroLengthBitField(Context))
continue;
QualType FieldType = Field->getType().getNonReferenceType();
@@ -12021,9 +12399,16 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
CopyConstructor->setParams(FromParam);
CopyConstructor->setTrivial(
- ClassDecl->needsOverloadResolutionForCopyConstructor()
- ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
- : ClassDecl->hasTrivialCopyConstructor());
+ ClassDecl->needsOverloadResolutionForCopyConstructor()
+ ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
+ : ClassDecl->hasTrivialCopyConstructor());
+
+ CopyConstructor->setTrivialForCall(
+ ClassDecl->hasAttr<TrivialABIAttr>() ||
+ (ClassDecl->needsOverloadResolutionForCopyConstructor()
+ ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor,
+ TAH_ConsiderTrivialABI)
+ : ClassDecl->hasTrivialCopyConstructorForCall()));
// Note that we have declared this constructor.
++ASTContext::NumImplicitCopyConstructorsDeclared;
@@ -12144,9 +12529,16 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
MoveConstructor->setParams(FromParam);
MoveConstructor->setTrivial(
- ClassDecl->needsOverloadResolutionForMoveConstructor()
- ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
- : ClassDecl->hasTrivialMoveConstructor());
+ ClassDecl->needsOverloadResolutionForMoveConstructor()
+ ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
+ : ClassDecl->hasTrivialMoveConstructor());
+
+ MoveConstructor->setTrivialForCall(
+ ClassDecl->hasAttr<TrivialABIAttr>() ||
+ (ClassDecl->needsOverloadResolutionForMoveConstructor()
+ ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor,
+ TAH_ConsiderTrivialABI)
+ : ClassDecl->hasTrivialMoveConstructorForCall()));
// Note that we have declared this constructor.
++ASTContext::NumImplicitMoveConstructorsDeclared;
@@ -12215,30 +12607,27 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
SourceLocation CurrentLocation,
CXXConversionDecl *Conv) {
SynthesizedFunctionScope Scope(*this, Conv);
+ assert(!Conv->getReturnType()->isUndeducedType());
CXXRecordDecl *Lambda = Conv->getParent();
- CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
- // If we are defining a specialization of a conversion to function-ptr
- // cache the deduced template arguments for this specialization
- // so that we can use them to retrieve the corresponding call-operator
- // and static-invoker.
- const TemplateArgumentList *DeducedTemplateArgs = nullptr;
-
- // Retrieve the corresponding call-operator specialization.
- if (Lambda->isGenericLambda()) {
- assert(Conv->isFunctionTemplateSpecialization());
- FunctionTemplateDecl *CallOpTemplate =
- CallOp->getDescribedFunctionTemplate();
- DeducedTemplateArgs = Conv->getTemplateSpecializationArgs();
- void *InsertPos = nullptr;
- FunctionDecl *CallOpSpec = CallOpTemplate->findSpecialization(
- DeducedTemplateArgs->asArray(),
- InsertPos);
- assert(CallOpSpec &&
- "Conversion operator must have a corresponding call operator");
- CallOp = cast<CXXMethodDecl>(CallOpSpec);
+ FunctionDecl *CallOp = Lambda->getLambdaCallOperator();
+ FunctionDecl *Invoker = Lambda->getLambdaStaticInvoker();
+
+ if (auto *TemplateArgs = Conv->getTemplateSpecializationArgs()) {
+ CallOp = InstantiateFunctionDeclaration(
+ CallOp->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation);
+ if (!CallOp)
+ return;
+
+ Invoker = InstantiateFunctionDeclaration(
+ Invoker->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation);
+ if (!Invoker)
+ return;
}
+ if (CallOp->isInvalidDecl())
+ return;
+
// Mark the call operator referenced (and add to pending instantiations
// if necessary).
// For both the conversion and static-invoker template specializations
@@ -12246,39 +12635,24 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
// to the PendingInstantiations.
MarkFunctionReferenced(CurrentLocation, CallOp);
- // Retrieve the static invoker...
- CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker();
- // ... and get the corresponding specialization for a generic lambda.
- if (Lambda->isGenericLambda()) {
- assert(DeducedTemplateArgs &&
- "Must have deduced template arguments from Conversion Operator");
- FunctionTemplateDecl *InvokeTemplate =
- Invoker->getDescribedFunctionTemplate();
- void *InsertPos = nullptr;
- FunctionDecl *InvokeSpec = InvokeTemplate->findSpecialization(
- DeducedTemplateArgs->asArray(),
- InsertPos);
- assert(InvokeSpec &&
- "Must have a corresponding static invoker specialization");
- Invoker = cast<CXXMethodDecl>(InvokeSpec);
- }
+ // Fill in the __invoke function with a dummy implementation. IR generation
+ // will fill in the actual details. Update its type in case it contained
+ // an 'auto'.
+ Invoker->markUsed(Context);
+ Invoker->setReferenced();
+ Invoker->setType(Conv->getReturnType()->getPointeeType());
+ Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));
+
// Construct the body of the conversion function { return __invoke; }.
Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->getType(),
- VK_LValue, Conv->getLocation()).get();
+ VK_LValue, Conv->getLocation()).get();
assert(FunctionRef && "Can't refer to __invoke function?");
Stmt *Return = BuildReturnStmt(Conv->getLocation(), FunctionRef).get();
Conv->setBody(CompoundStmt::Create(Context, Return, Conv->getLocation(),
Conv->getLocation()));
-
Conv->markUsed(Context);
Conv->setReferenced();
- // Fill in the __invoke function with a dummy implementation. IR generation
- // will fill in the actual details.
- Invoker->markUsed(Context);
- Invoker->setReferenced();
- Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));
-
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Conv);
L->CompletedImplicitDefinition(Invoker);
@@ -12339,7 +12713,7 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
}
}
-/// \brief Determine whether the given list arguments contains exactly one
+/// Determine whether the given list arguments contains exactly one
/// "real" (non-default) argument.
static bool hasOneRealArgument(MultiExprArg Args) {
switch (Args.size()) {
@@ -12550,7 +12924,7 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
Diag(VD->getLocation(), diag::warn_global_destructor);
}
-/// \brief Given a constructor and the set of arguments provided for the
+/// Given a constructor and the set of arguments provided for the
/// constructor, convert the arguments and add any required default arguments
/// to form a proper call to this constructor.
///
@@ -12617,6 +12991,13 @@ CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef,
return false;
}
+static QualType
+RemoveAddressSpaceFromPtr(Sema &SemaRef, const PointerType *PtrTy) {
+ QualType QTy = PtrTy->getPointeeType();
+ QTy = SemaRef.Context.removeAddrSpaceQualType(QTy);
+ return SemaRef.Context.getPointerType(QTy);
+}
+
static inline bool
CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
CanQualType ExpectedResultType,
@@ -12632,6 +13013,13 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
diag::err_operator_new_delete_dependent_result_type)
<< FnDecl->getDeclName() << ExpectedResultType;
+ // OpenCL C++: the operator is valid on any address space.
+ if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
+ if (auto *PtrTy = ResultType->getAs<PointerType>()) {
+ ResultType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy);
+ }
+ }
+
// Check that the result type is what we expect.
if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType)
return SemaRef.Diag(FnDecl->getLocation(),
@@ -12657,6 +13045,13 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
<< FnDecl->getDeclName() << ExpectedFirstParamType;
// Check that the first parameter type is what we expect.
+ if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
+ // OpenCL C++: the operator is valid on any address space.
+ if (auto *PtrTy =
+ FnDecl->getParamDecl(0)->getType()->getAs<PointerType>()) {
+ FirstParamType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy);
+ }
+ }
if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() !=
ExpectedFirstParamType)
return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag)
@@ -12966,6 +13361,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
ParamType->isSpecificBuiltinType(BuiltinType::LongDouble) ||
Context.hasSameType(ParamType, Context.CharTy) ||
Context.hasSameType(ParamType, Context.WideCharTy) ||
+ Context.hasSameType(ParamType, Context.Char8Ty) ||
Context.hasSameType(ParamType, Context.Char16Ty) ||
Context.hasSameType(ParamType, Context.Char32Ty)) {
} else if (const PointerType *Ptr = ParamType->getAs<PointerType>()) {
@@ -13026,10 +13422,12 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
}
QualType InnerType = PointeeType.getUnqualifiedType();
- // Only const char *, const wchar_t*, const char16_t*, and const char32_t*
- // are allowed as the first parameter to a two-parameter function
+ // Only const char *, const wchar_t*, const char8_t*, const char16_t*, and
+ // const char32_t* are allowed as the first parameter to a two-parameter
+ // function
if (!(Context.hasSameType(InnerType, Context.CharTy) ||
Context.hasSameType(InnerType, Context.WideCharTy) ||
+ Context.hasSameType(InnerType, Context.Char8Ty) ||
Context.hasSameType(InnerType, Context.Char16Ty) ||
Context.hasSameType(InnerType, Context.Char32Ty))) {
Diag((*Param)->getSourceRange().getBegin(),
@@ -13136,19 +13534,18 @@ Decl *Sema::ActOnFinishLinkageSpecification(Scope *S,
}
Decl *Sema::ActOnEmptyDeclaration(Scope *S,
- AttributeList *AttrList,
+ const ParsedAttributesView &AttrList,
SourceLocation SemiLoc) {
Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc);
// Attribute declarations appertain to empty declaration so we handle
// them here.
- if (AttrList)
- ProcessDeclAttributeList(S, ED, AttrList);
+ ProcessDeclAttributeList(S, ED, AttrList);
CurContext->addDecl(ED);
return ED;
}
-/// \brief Perform semantic analysis for the variable declaration that
+/// Perform semantic analysis for the variable declaration that
/// occurs within a C++ catch clause, returning the newly-created
/// variable.
VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
@@ -13404,7 +13801,7 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
return Decl;
}
-/// \brief Perform semantic analysis of the given friend type declaration.
+/// Perform semantic analysis of the given friend type declaration.
///
/// \returns A friend declaration that.
FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
@@ -13481,10 +13878,9 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
/// templated.
Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
unsigned TagSpec, SourceLocation TagLoc,
- CXXScopeSpec &SS,
- IdentifierInfo *Name,
+ CXXScopeSpec &SS, IdentifierInfo *Name,
SourceLocation NameLoc,
- AttributeList *Attr,
+ const ParsedAttributesView &Attr,
MultiTemplateParamsArg TempParamLists) {
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
@@ -13597,7 +13993,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
return Friend;
}
-
/// Handle a friend type declaration. This works in tandem with
/// ActOnTag.
///
@@ -13625,7 +14020,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
// Try to convert the decl specifier to a type. This works for
// friend templates because ActOnTag never produces a ClassTemplateDecl
// for a TUK_Friend.
- Declarator TheDeclarator(DS, Declarator::MemberContext);
+ Declarator TheDeclarator(DS, DeclaratorContext::MemberContext);
TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S);
QualType T = TSI->getType();
if (TheDeclarator.isInvalidType())
@@ -13799,7 +14194,8 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
// elaborated-type-specifier, the lookup to determine whether
// the entity has been previously declared shall not consider
// any scopes outside the innermost enclosing namespace.
- bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId;
+ bool isTemplateId =
+ D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId;
// Find the appropriate context according to the above.
DC = CurContext;
@@ -13910,24 +14306,24 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
if (!DC->isRecord()) {
int DiagArg = -1;
switch (D.getName().getKind()) {
- case UnqualifiedId::IK_ConstructorTemplateId:
- case UnqualifiedId::IK_ConstructorName:
+ case UnqualifiedIdKind::IK_ConstructorTemplateId:
+ case UnqualifiedIdKind::IK_ConstructorName:
DiagArg = 0;
break;
- case UnqualifiedId::IK_DestructorName:
+ case UnqualifiedIdKind::IK_DestructorName:
DiagArg = 1;
break;
- case UnqualifiedId::IK_ConversionFunctionId:
+ case UnqualifiedIdKind::IK_ConversionFunctionId:
DiagArg = 2;
break;
- case UnqualifiedId::IK_DeductionGuideName:
+ case UnqualifiedIdKind::IK_DeductionGuideName:
DiagArg = 3;
break;
- case UnqualifiedId::IK_Identifier:
- case UnqualifiedId::IK_ImplicitSelfParam:
- case UnqualifiedId::IK_LiteralOperatorId:
- case UnqualifiedId::IK_OperatorFunctionId:
- case UnqualifiedId::IK_TemplateId:
+ case UnqualifiedIdKind::IK_Identifier:
+ case UnqualifiedIdKind::IK_ImplicitSelfParam:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_TemplateId:
break;
}
// This implies that it has to be an operator or function.
@@ -14168,6 +14564,16 @@ bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
}
}
+ // Virtual overrides must have the same code_seg.
+ const auto *OldCSA = Old->getAttr<CodeSegAttr>();
+ const auto *NewCSA = New->getAttr<CodeSegAttr>();
+ if ((NewCSA || OldCSA) &&
+ (!OldCSA || !NewCSA || NewCSA->getName() != OldCSA->getName())) {
+ Diag(New->getLocation(), diag::err_mismatched_code_seg_override);
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ return true;
+ }
+
CallingConv NewCC = NewFT->getCallConv(), OldCC = OldFT->getCallConv();
// If the calling conventions match, everything is fine
@@ -14294,7 +14700,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
return false;
}
-/// \brief Mark the given method pure.
+/// Mark the given method pure.
///
/// \param Method the method to be marked pure.
///
@@ -14324,7 +14730,7 @@ void Sema::ActOnPureSpecifier(Decl *D, SourceLocation ZeroLoc) {
Diag(D->getLocation(), diag::err_illegal_initializer);
}
-/// \brief Determine whether the given declaration is a global variable or
+/// Determine whether the given declaration is a global variable or
/// static data member.
static bool isNonlocalVariable(const Decl *D) {
if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D))
@@ -14431,7 +14837,7 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
// Try to insert this class into the map.
LoadExternalVTableUses();
- Class = cast<CXXRecordDecl>(Class->getCanonicalDecl());
+ Class = Class->getCanonicalDecl();
std::pair<llvm::DenseMap<CXXRecordDecl *, bool>::iterator, bool>
Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired));
if (!Pos.second) {
@@ -14543,7 +14949,7 @@ bool Sema::DefineUsedVTables() {
// vtable for this class is required.
DefinedAnything = true;
MarkVirtualMembersReferenced(Loc, Class);
- CXXRecordDecl *Canonical = cast<CXXRecordDecl>(Class->getCanonicalDecl());
+ CXXRecordDecl *Canonical = Class->getCanonicalDecl();
if (VTablesUsed[Canonical])
Consumer.HandleVTable(Class);
@@ -14666,9 +15072,9 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
static
void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
- llvm::SmallSet<CXXConstructorDecl*, 4> &Valid,
- llvm::SmallSet<CXXConstructorDecl*, 4> &Invalid,
- llvm::SmallSet<CXXConstructorDecl*, 4> &Current,
+ llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Valid,
+ llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Invalid,
+ llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Current,
Sema &S) {
if (Ctor->isInvalidDecl())
return;
@@ -14730,7 +15136,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
void Sema::CheckDelegatingCtorCycles() {
- llvm::SmallSet<CXXConstructorDecl*, 4> Valid, Invalid, Current;
+ llvm::SmallPtrSet<CXXConstructorDecl*, 4> Valid, Invalid, Current;
for (DelegatingCtorDeclsType::iterator
I = DelegatingCtorDecls.begin(ExternalSource),
@@ -14738,14 +15144,12 @@ void Sema::CheckDelegatingCtorCycles() {
I != E; ++I)
DelegatingCycleHelper(*I, Valid, Invalid, Current, *this);
- for (llvm::SmallSet<CXXConstructorDecl *, 4>::iterator CI = Invalid.begin(),
- CE = Invalid.end();
- CI != CE; ++CI)
+ for (auto CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI)
(*CI)->setInvalidDecl();
}
namespace {
- /// \brief AST visitor that finds references to the 'this' expression.
+ /// AST visitor that finds references to the 'this' expression.
class FindCXXThisExpr : public RecursiveASTVisitor<FindCXXThisExpr> {
Sema &S;
@@ -14815,7 +15219,9 @@ bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) {
case EST_None:
break;
- case EST_ComputedNoexcept:
+ case EST_DependentNoexcept:
+ case EST_NoexceptFalse:
+ case EST_NoexceptTrue:
if (!Finder.TraverseStmt(Proto->getNoexceptExpr()))
return true;
LLVM_FALLTHROUGH;
@@ -14912,31 +15318,17 @@ void Sema::checkExceptionSpecification(
return;
}
- if (EST == EST_ComputedNoexcept) {
- // If an error occurred, there's no expression here.
- if (NoexceptExpr) {
- assert((NoexceptExpr->isTypeDependent() ||
- NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
- Context.BoolTy) &&
- "Parser should have made sure that the expression is boolean");
- if (IsTopLevel && NoexceptExpr &&
- DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
- ESI.Type = EST_BasicNoexcept;
- return;
- }
-
- if (!NoexceptExpr->isValueDependent()) {
- ExprResult Result = VerifyIntegerConstantExpression(
- NoexceptExpr, nullptr, diag::err_noexcept_needs_constant_expression,
- /*AllowFold*/ false);
- if (Result.isInvalid()) {
- ESI.Type = EST_BasicNoexcept;
- return;
- }
- NoexceptExpr = Result.get();
- }
- ESI.NoexceptExpr = NoexceptExpr;
+ if (isComputedNoexcept(EST)) {
+ assert((NoexceptExpr->isTypeDependent() ||
+ NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
+ Context.BoolTy) &&
+ "Parser should have made sure that the expression is boolean");
+ if (IsTopLevel && DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
+ ESI.Type = EST_BasicNoexcept;
+ return;
}
+
+ ESI.NoexceptExpr = NoexceptExpr;
return;
}
}
@@ -14981,11 +15373,11 @@ void Sema::actOnDelayedExceptionSpecification(Decl *MethodD,
/// HandleMSProperty - Analyze a __delcspec(property) field of a C++ class.
///
MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
- SourceLocation DeclStart,
- Declarator &D, Expr *BitWidth,
+ SourceLocation DeclStart, Declarator &D,
+ Expr *BitWidth,
InClassInitStyle InitStyle,
AccessSpecifier AS,
- AttributeList *MSPropertyAttr) {
+ const ParsedAttr &MSPropertyAttr) {
IdentifierInfo *II = D.getIdentifier();
if (!II) {
Diag(DeclStart, diag::err_anonymous_property);
@@ -15048,7 +15440,7 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
PrevDecl = nullptr;
SourceLocation TSSL = D.getLocStart();
- const AttributeList::PropertyData &Data = MSPropertyAttr->getPropertyData();
+ const ParsedAttr::PropertyData &Data = MSPropertyAttr.getPropertyData();
MSPropertyDecl *NewPD = MSPropertyDecl::Create(
Context, Record, Loc, II, T, TInfo, TSSL, Data.GetterId, Data.SetterId);
ProcessDeclAttributes(TUScope, NewPD, D);