summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
committerdim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
commit9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch)
treec978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
parent03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff)
downloadFreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip
FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports all of the features in the current working draft of the upcoming C++ standard, provisionally named C++1y. The code generator's performance is greatly increased, and the loop auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The PowerPC backend has made several major improvements to code generation quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ backends have all seen major feature work. Release notes for llvm and clang can be found here: <http://llvm.org/releases/3.4/docs/ReleaseNotes.html> <http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html> MFC 262121 (by emaste): Update lldb for clang/llvm 3.4 import This commit largely restores the lldb source to the upstream r196259 snapshot with the addition of threaded inferior support and a few bug fixes. Specific upstream lldb revisions restored include: SVN git 181387 779e6ac 181703 7bef4e2 182099 b31044e 182650 f2dcf35 182683 0d91b80 183862 15c1774 183929 99447a6 184177 0b2934b 184948 4dc3761 184954 007e7bc 186990 eebd175 Sponsored by: DARPA, AFRL MFC 262186 (by emaste): Fix mismerge in r262121 A break statement was lost in the merge. The error had no functional impact, but restore it to reduce the diff against upstream. MFC 262303: Pull in r197521 from upstream clang trunk (by rdivacky): Use the integrated assembler by default on FreeBSD/ppc and ppc64. Requested by: jhibbits MFC 262611: Pull in r196874 from upstream llvm trunk: Fix a crash that occurs when PWD is invalid. MCJIT needs to be able to run in hostile environments, even when PWD is invalid. There's no need to crash MCJIT in this case. The obvious fix is to simply leave MCContext's CompilationDir empty when PWD can't be determined. This way, MCJIT clients, and other clients that link with LLVM don't need a valid working directory. If we do want to guarantee valid CompilationDir, that should be done only for clients of getCompilationDir(). This is as simple as checking for an empty string. The only current use of getCompilationDir is EmitGenDwarfInfo, which won't conceivably run with an invalid working dir. However, in the purely hypothetically and untestable case that this happens, the AT_comp_dir will be omitted from the compilation_unit DIE. This should help fix assertions occurring with ports-mgmt/tinderbox, when it is using jails, and sometimes invalidates clang's current working directory. Reported by: decke MFC 262809: Pull in r203007 from upstream clang trunk: Don't produce an alias between destructors with different calling conventions. Fixes pr19007. (Please note that is an LLVM PR identifier, not a FreeBSD one.) This should fix Firefox and/or libxul crashes (due to problems with regparm/stdcall calling conventions) on i386. Reported by: multiple users on freebsd-current PR: bin/187103 MFC 263048: Repair recognition of "CC" as an alias for the C++ compiler, since it was silently broken by upstream for a Windows-specific use-case. Apparently some versions of CMake still rely on this archaic feature... Reported by: rakuco MFC 263049: Garbage collect the old way of adding the libstdc++ include directories in clang's InitHeaderSearch.cpp. This has been superseded by David Chisnall's commit in r255321. Moreover, if libc++ is used, the libstdc++ include directories should not be in the search path at all. These directories are now only used if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp2108
1 files changed, 1302 insertions, 806 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
index e6a131a..6b3400a 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
@@ -14,6 +14,7 @@
#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
@@ -27,6 +28,7 @@
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/DeclSpec.h"
@@ -339,9 +341,7 @@ void Sema::ActOnParamUnparsedDefaultArgument(Decl *param,
return;
ParmVarDecl *Param = cast<ParmVarDecl>(param);
- if (Param)
- Param->setUnparsedDefaultArg();
-
+ Param->setUnparsedDefaultArg();
UnparsedDefaultArgLocs[Param] = ArgLoc;
}
@@ -352,9 +352,7 @@ void Sema::ActOnParamDefaultArgumentError(Decl *param) {
return;
ParmVarDecl *Param = cast<ParmVarDecl>(param);
-
Param->setInvalidDecl();
-
UnparsedDefaultArgLocs.erase(Param);
}
@@ -404,6 +402,17 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
}
}
+static bool functionDeclHasDefaultArgument(const FunctionDecl *FD) {
+ for (unsigned NumParams = FD->getNumParams(); NumParams > 0; --NumParams) {
+ const ParmVarDecl *PVD = FD->getParamDecl(NumParams-1);
+ if (!PVD->hasDefaultArg())
+ return false;
+ if (!PVD->hasInheritedDefaultArg())
+ return true;
+ }
+ return false;
+}
+
/// MergeCXXFunctionDecl - Merge two declarations of the same C++
/// function, once we already know that they have the same
/// type. Subroutine of MergeFunctionDecl. Returns true if there was an
@@ -426,9 +435,9 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
// declaration (not even to the same value).
//
// C++ [dcl.fct.default]p6:
- // Except for member functions of class templates, the default arguments
- // in a member function definition that appears outside of the class
- // definition are added to the set of default arguments provided by the
+ // Except for member functions of class templates, the default arguments
+ // in a member function definition that appears outside of the class
+ // definition are added to the set of default arguments provided by the
// member function declaration in the class definition.
for (unsigned p = 0, NumParams = Old->getNumParams(); p < NumParams; ++p) {
ParmVarDecl *OldParam = Old->getParamDecl(p);
@@ -438,9 +447,18 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
bool NewParamHasDfl = NewParam->hasDefaultArg();
NamedDecl *ND = Old;
- if (S && !isDeclInScope(ND, New->getDeclContext(), S))
+
+ // The declaration context corresponding to the scope is the semantic
+ // parent, unless this is a local function declaration, in which case
+ // it is that surrounding function.
+ DeclContext *ScopeDC = New->getLexicalDeclContext();
+ if (!ScopeDC->isFunctionOrMethod())
+ ScopeDC = New->getDeclContext();
+ if (S && !isDeclInScope(ND, ScopeDC, S) &&
+ !New->getDeclContext()->isRecord())
// Ignore default parameters of old decl if they are not in
- // the same scope.
+ // the same scope and this is not an out-of-line definition of
+ // a member function.
OldParamHasDfl = false;
if (OldParamHasDfl && NewParamHasDfl) {
@@ -578,6 +596,17 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
Invalid = true;
}
+ // C++11 [dcl.fct.default]p4: If a friend declaration specifies a default
+ // argument expression, that declaration shall be a definition and shall be
+ // the only declaration of the function or function template in the
+ // translation unit.
+ if (Old->getFriendObjectKind() == Decl::FOK_Undeclared &&
+ functionDeclHasDefaultArgument(Old)) {
+ Diag(New->getLocation(), diag::err_friend_decl_with_def_arg_redeclared);
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ Invalid = true;
+ }
+
if (CheckEquivalentExceptionSpec(Old, New))
Invalid = true;
@@ -851,7 +880,7 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
diag::err_constexpr_local_var_non_literal_type,
isa<CXXConstructorDecl>(Dcl)))
return false;
- if (!VD->hasInit()) {
+ if (!VD->hasInit() && !VD->isCXXForRangeDecl()) {
SemaRef.Diag(VD->getLocation(),
diag::err_constexpr_local_var_no_init)
<< isa<CXXConstructorDecl>(Dcl);
@@ -897,6 +926,9 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef,
FieldDecl *Field,
llvm::SmallSet<Decl*, 16> &Inits,
bool &Diagnosed) {
+ if (Field->isInvalidDecl())
+ return;
+
if (Field->isUnnamedBitfield())
return;
@@ -925,7 +957,7 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef,
/// definition.
static bool
CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
- llvm::SmallVectorImpl<SourceLocation> &ReturnStmts,
+ SmallVectorImpl<SourceLocation> &ReturnStmts,
SourceLocation &Cxx1yLoc) {
// - its function-body shall be [...] a compound-statement that contains only
switch (S->getStmtClass()) {
@@ -1192,8 +1224,33 @@ bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *,
if (CurDecl && CurDecl->getIdentifier())
return &II == CurDecl->getIdentifier();
- else
+ return false;
+}
+
+/// \brief 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) {
+ assert(getLangOpts().CPlusPlus && "No class names in C!");
+
+ if (!getLangOpts().SpellChecking)
return false;
+
+ 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() && II != CurDecl->getIdentifier() &&
+ 3 * II->getName().edit_distance(CurDecl->getIdentifier()->getName())
+ < II->getLength()) {
+ II = CurDecl->getIdentifier();
+ return true;
+ }
+
+ return false;
}
/// \brief Determine whether the given class is a base class of the given
@@ -1224,8 +1281,7 @@ static bool findCircularInheritance(const CXXRecordDecl *Class,
if (Queue.empty())
return false;
- Current = Queue.back();
- Queue.pop_back();
+ Current = Queue.pop_back_val();
}
return false;
@@ -1311,15 +1367,28 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
assert(BaseDecl && "Record type has no declaration");
BaseDecl = BaseDecl->getDefinition();
assert(BaseDecl && "Base type is not incomplete, but has no definition");
- CXXRecordDecl * CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
+ CXXRecordDecl *CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
assert(CXXBaseDecl && "Base type is not a C++ type");
+ // 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,
+ // the flexible array member would index into the subsequent base.
+ // - If the layout determines that base comes before the derived class,
+ // the flexible array member would index into the derived class.
+ if (CXXBaseDecl->hasFlexibleArrayMember()) {
+ Diag(BaseLoc, diag::err_base_class_has_flexible_array_member)
+ << CXXBaseDecl->getDeclName();
+ return 0;
+ }
+
// C++ [class]p3:
- // If a class is marked final and it appears as a base-type-specifier in
+ // If a class is marked final and it appears as a base-type-specifier in
// base-clause, the program is ill-formed.
- if (CXXBaseDecl->hasAttr<FinalAttr>()) {
- Diag(BaseLoc, diag::err_class_marked_final_used_as_base)
- << CXXBaseDecl->getDeclName();
+ if (FinalAttr *FA = CXXBaseDecl->getAttr<FinalAttr>()) {
+ Diag(BaseLoc, diag::err_class_marked_final_used_as_base)
+ << CXXBaseDecl->getDeclName()
+ << FA->isSpelledAsSealed();
Diag(CXXBaseDecl->getLocation(), diag::note_previous_decl)
<< CXXBaseDecl->getDeclName();
return 0;
@@ -1327,7 +1396,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
if (BaseDecl->isInvalidDecl())
Class->setInvalidDecl();
-
+
// Create the base specifier.
return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
Class->getTagKind() == TTK_Class,
@@ -1465,8 +1534,7 @@ void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, CXXBaseSpecifier **Bases,
return;
AdjustDeclIfTemplate(ClassDecl);
- AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl),
- (CXXBaseSpecifier**)(Bases), NumBases);
+ AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases, NumBases);
}
/// \brief Determine whether the type \p Derived is a C++ class that is
@@ -1590,26 +1658,28 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
return false;
}
- // We know that the derived-to-base conversion is ambiguous, and
- // we're going to produce a diagnostic. Perform the derived-to-base
- // search just one more time to compute all of the possible paths so
- // that we can print them out. This is more expensive than any of
- // the previous derived-to-base checks we've done, but at this point
- // performance isn't as much of an issue.
- Paths.clear();
- Paths.setRecordingPaths(true);
- bool StillOkay = IsDerivedFrom(Derived, Base, Paths);
- assert(StillOkay && "Can only be used with a derived-to-base conversion");
- (void)StillOkay;
-
- // Build up a textual representation of the ambiguous paths, e.g.,
- // D -> B -> A, that will be used to illustrate the ambiguous
- // conversions in the diagnostic. We only print one of the paths
- // to each base class subobject.
- std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);
-
- Diag(Loc, AmbigiousBaseConvID)
- << Derived << Base << PathDisplayStr << Range << Name;
+ if (AmbigiousBaseConvID) {
+ // We know that the derived-to-base conversion is ambiguous, and
+ // we're going to produce a diagnostic. Perform the derived-to-base
+ // search just one more time to compute all of the possible paths so
+ // that we can print them out. This is more expensive than any of
+ // the previous derived-to-base checks we've done, but at this point
+ // performance isn't as much of an issue.
+ Paths.clear();
+ Paths.setRecordingPaths(true);
+ bool StillOkay = IsDerivedFrom(Derived, Base, Paths);
+ assert(StillOkay && "Can only be used with a derived-to-base conversion");
+ (void)StillOkay;
+
+ // Build up a textual representation of the ambiguous paths, e.g.,
+ // D -> B -> A, that will be used to illustrate the ambiguous
+ // conversions in the diagnostic. We only print one of the paths
+ // to each base class subobject.
+ std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);
+
+ Diag(Loc, AmbigiousBaseConvID)
+ << Derived << Base << PathDisplayStr << Range << Name;
+ }
return true;
}
@@ -1675,37 +1745,63 @@ bool Sema::ActOnAccessSpecifier(AccessSpecifier Access,
}
/// CheckOverrideControl - Check C++11 override control semantics.
-void Sema::CheckOverrideControl(Decl *D) {
+void Sema::CheckOverrideControl(NamedDecl *D) {
if (D->isInvalidDecl())
return;
- const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D);
+ // We only care about "override" and "final" declarations.
+ if (!D->hasAttr<OverrideAttr>() && !D->hasAttr<FinalAttr>())
+ return;
- // Do we know which functions this declaration might be overriding?
- bool OverridesAreKnown = !MD ||
- (!MD->getParent()->hasAnyDependentBases() &&
- !MD->getType()->isDependentType());
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D);
- if (!MD || !MD->isVirtual()) {
- if (OverridesAreKnown) {
+ // We can't check dependent instance methods.
+ if (MD && MD->isInstance() &&
+ (MD->getParent()->hasAnyDependentBases() ||
+ MD->getType()->isDependentType()))
+ return;
+
+ if (MD && !MD->isVirtual()) {
+ // If we have a non-virtual method, check if if hides a virtual method.
+ // (In that case, it's most likely the method has the wrong type.)
+ SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
+ FindHiddenVirtualMethods(MD, OverloadedMethods);
+
+ if (!OverloadedMethods.empty()) {
if (OverrideAttr *OA = D->getAttr<OverrideAttr>()) {
Diag(OA->getLocation(),
- diag::override_keyword_only_allowed_on_virtual_member_functions)
- << "override" << FixItHint::CreateRemoval(OA->getLocation());
- D->dropAttr<OverrideAttr>();
- }
- if (FinalAttr *FA = D->getAttr<FinalAttr>()) {
+ diag::override_keyword_hides_virtual_member_function)
+ << "override" << (OverloadedMethods.size() > 1);
+ } else if (FinalAttr *FA = D->getAttr<FinalAttr>()) {
Diag(FA->getLocation(),
- diag::override_keyword_only_allowed_on_virtual_member_functions)
- << "final" << FixItHint::CreateRemoval(FA->getLocation());
- D->dropAttr<FinalAttr>();
+ diag::override_keyword_hides_virtual_member_function)
+ << (FA->isSpelledAsSealed() ? "sealed" : "final")
+ << (OverloadedMethods.size() > 1);
}
+ NoteHiddenVirtualMethods(MD, OverloadedMethods);
+ MD->setInvalidDecl();
+ return;
}
- return;
+ // Fall through into the general case diagnostic.
+ // FIXME: We might want to attempt typo correction here.
}
- if (!OverridesAreKnown)
+ if (!MD || !MD->isVirtual()) {
+ if (OverrideAttr *OA = D->getAttr<OverrideAttr>()) {
+ Diag(OA->getLocation(),
+ diag::override_keyword_only_allowed_on_virtual_member_functions)
+ << "override" << FixItHint::CreateRemoval(OA->getLocation());
+ D->dropAttr<OverrideAttr>();
+ }
+ if (FinalAttr *FA = D->getAttr<FinalAttr>()) {
+ Diag(FA->getLocation(),
+ diag::override_keyword_only_allowed_on_virtual_member_functions)
+ << (FA->isSpelledAsSealed() ? "sealed" : "final")
+ << FixItHint::CreateRemoval(FA->getLocation());
+ D->dropAttr<FinalAttr>();
+ }
return;
+ }
// C++11 [class.virtual]p5:
// If a virtual function is marked with the virt-specifier override and
@@ -1723,11 +1819,13 @@ void Sema::CheckOverrideControl(Decl *D) {
/// C++11 [class.virtual]p4.
bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,
const CXXMethodDecl *Old) {
- if (!Old->hasAttr<FinalAttr>())
+ FinalAttr *FA = Old->getAttr<FinalAttr>();
+ if (!FA)
return false;
Diag(New->getLocation(), diag::err_final_function_overridden)
- << New->getDeclName();
+ << New->getDeclName()
+ << FA->isSpelledAsSealed();
Diag(Old->getLocation(), diag::note_overridden_virtual_function);
return true;
}
@@ -1933,19 +2031,20 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
if (MSPropertyAttr) {
Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D,
BitWidth, InitStyle, AS, MSPropertyAttr);
+ if (!Member)
+ return 0;
isInstField = false;
} else {
Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D,
BitWidth, InitStyle, AS);
+ assert(Member && "HandleField never returns null");
}
- assert(Member && "HandleField never returns null");
} else {
assert(InitStyle == ICIS_NoInit || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static);
Member = HandleDeclarator(S, D, TemplateParameterLists);
- if (!Member) {
+ if (!Member)
return 0;
- }
// Non-instance-fields can't have a bitfield.
if (BitWidth) {
@@ -1974,16 +2073,19 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
Member->setAccess(AS);
- // If we have declared a member function template, set the access of the
- // templated declaration as well.
+ // 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 (VS.isOverrideSpecified())
Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context));
if (VS.isFinalSpecified())
- Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context));
+ Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context,
+ VS.isFinalSpelledSealed()));
if (VS.getLastLocation().isValid()) {
// Update the end location of a method that has a virt-specifiers.
@@ -2020,57 +2122,71 @@ namespace {
class UninitializedFieldVisitor
: public EvaluatedExprVisitor<UninitializedFieldVisitor> {
Sema &S;
- ValueDecl *VD;
+ // List of Decls to generate a warning on. Also remove Decls that become
+ // initialized.
+ llvm::SmallPtrSet<ValueDecl*, 4> &Decls;
+ // If non-null, add a note to the warning pointing back to the constructor.
+ const CXXConstructorDecl *Constructor;
public:
typedef EvaluatedExprVisitor<UninitializedFieldVisitor> Inherited;
- UninitializedFieldVisitor(Sema &S, ValueDecl *VD) : Inherited(S.Context),
- S(S) {
- if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(VD))
- this->VD = IFD->getAnonField();
- else
- this->VD = VD;
- }
-
- void HandleExpr(Expr *E) {
- if (!E) return;
+ UninitializedFieldVisitor(Sema &S,
+ llvm::SmallPtrSet<ValueDecl*, 4> &Decls,
+ const CXXConstructorDecl *Constructor)
+ : Inherited(S.Context), S(S), Decls(Decls),
+ Constructor(Constructor) { }
+
+ void HandleMemberExpr(MemberExpr *ME, bool CheckReferenceOnly) {
+ if (isa<EnumConstantDecl>(ME->getMemberDecl()))
+ return;
- // Expressions like x(x) sometimes lack the surrounding expressions
- // but need to be checked anyways.
- HandleValue(E);
- Visit(E);
- }
+ // FieldME is the inner-most MemberExpr that is not an anonymous struct
+ // or union.
+ MemberExpr *FieldME = ME;
- void HandleValue(Expr *E) {
- E = E->IgnoreParens();
+ Expr *Base = ME;
+ while (isa<MemberExpr>(Base)) {
+ ME = cast<MemberExpr>(Base);
- if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
- if (isa<EnumConstantDecl>(ME->getMemberDecl()))
+ if (isa<VarDecl>(ME->getMemberDecl()))
return;
- // FieldME is the inner-most MemberExpr that is not an anonymous struct
- // or union.
- MemberExpr *FieldME = ME;
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
+ if (!FD->isAnonymousStructOrUnion())
+ FieldME = ME;
- Expr *Base = E;
- while (isa<MemberExpr>(Base)) {
- ME = cast<MemberExpr>(Base);
+ Base = ME->getBase();
+ }
- if (isa<VarDecl>(ME->getMemberDecl()))
- return;
+ if (!isa<CXXThisExpr>(Base))
+ return;
- if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
- if (!FD->isAnonymousStructOrUnion())
- FieldME = ME;
+ ValueDecl* FoundVD = FieldME->getMemberDecl();
- Base = ME->getBase();
- }
+ if (!Decls.count(FoundVD))
+ return;
- if (VD == FieldME->getMemberDecl() && isa<CXXThisExpr>(Base)) {
- unsigned diag = VD->getType()->isReferenceType()
- ? diag::warn_reference_field_is_uninit
- : diag::warn_field_is_uninit;
- S.Diag(FieldME->getExprLoc(), diag) << VD;
- }
+ const bool IsReference = FoundVD->getType()->isReferenceType();
+
+ // Prevent double warnings on use of unbounded references.
+ if (IsReference != CheckReferenceOnly)
+ return;
+
+ unsigned diag = IsReference
+ ? diag::warn_reference_field_is_uninit
+ : diag::warn_field_is_uninit;
+ S.Diag(FieldME->getExprLoc(), diag) << FoundVD;
+ if (Constructor)
+ S.Diag(Constructor->getLocation(),
+ diag::note_uninit_in_this_constructor)
+ << (Constructor->isDefaultConstructor() && Constructor->isImplicit());
+
+ }
+
+ void HandleValue(Expr *E) {
+ E = E->IgnoreParens();
+
+ if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+ HandleMemberExpr(ME, false /*CheckReferenceOnly*/);
return;
}
@@ -2102,6 +2218,13 @@ namespace {
}
}
+ void VisitMemberExpr(MemberExpr *ME) {
+ // All uses of unbounded reference fields will warn.
+ HandleMemberExpr(ME, true /*CheckReferenceOnly*/);
+
+ Inherited::VisitMemberExpr(ME);
+ }
+
void VisitImplicitCastExpr(ImplicitCastExpr *E) {
if (E->getCastKind() == CK_LValueToRValue)
HandleValue(E->getSubExpr());
@@ -2109,6 +2232,16 @@ namespace {
Inherited::VisitImplicitCastExpr(E);
}
+ void VisitCXXConstructExpr(CXXConstructExpr *E) {
+ if (E->getConstructor()->isCopyConstructor())
+ if (ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(E->getArg(0)))
+ if (ICE->getCastKind() == CK_NoOp)
+ if (MemberExpr *ME = dyn_cast<MemberExpr>(ICE->getSubExpr()))
+ HandleMemberExpr(ME, false /*CheckReferenceOnly*/);
+
+ Inherited::VisitCXXConstructExpr(E);
+ }
+
void VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
Expr *Callee = E->getCallee();
if (isa<MemberExpr>(Callee))
@@ -2116,10 +2249,85 @@ namespace {
Inherited::VisitCXXMemberCallExpr(E);
}
+
+ void VisitBinaryOperator(BinaryOperator *E) {
+ // If a field assignment is detected, remove the field from the
+ // uninitiailized field set.
+ if (E->getOpcode() == BO_Assign)
+ if (MemberExpr *ME = dyn_cast<MemberExpr>(E->getLHS()))
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
+ if (!FD->getType()->isReferenceType())
+ Decls.erase(FD);
+
+ Inherited::VisitBinaryOperator(E);
+ }
};
- static void CheckInitExprContainsUninitializedFields(Sema &S, Expr *E,
- ValueDecl *VD) {
- UninitializedFieldVisitor(S, VD).HandleExpr(E);
+ static void CheckInitExprContainsUninitializedFields(
+ Sema &S, Expr *E, llvm::SmallPtrSet<ValueDecl*, 4> &Decls,
+ const CXXConstructorDecl *Constructor) {
+ if (Decls.size() == 0)
+ return;
+
+ if (!E)
+ return;
+
+ if (CXXDefaultInitExpr *Default = dyn_cast<CXXDefaultInitExpr>(E)) {
+ E = Default->getExpr();
+ if (!E)
+ return;
+ // In class initializers will point to the constructor.
+ UninitializedFieldVisitor(S, Decls, Constructor).Visit(E);
+ } else {
+ UninitializedFieldVisitor(S, Decls, 0).Visit(E);
+ }
+ }
+
+ // Diagnose value-uses of fields to initialize themselves, e.g.
+ // foo(foo)
+ // where foo is not also a parameter to the constructor.
+ // Also diagnose across field uninitialized use such as
+ // x(y), y(x)
+ // TODO: implement -Wuninitialized and fold this into that framework.
+ static void DiagnoseUninitializedFields(
+ Sema &SemaRef, const CXXConstructorDecl *Constructor) {
+
+ if (SemaRef.getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit,
+ Constructor->getLocation())
+ == DiagnosticsEngine::Ignored) {
+ return;
+ }
+
+ if (Constructor->isInvalidDecl())
+ return;
+
+ const CXXRecordDecl *RD = Constructor->getParent();
+
+ // Holds fields that are uninitialized.
+ llvm::SmallPtrSet<ValueDecl*, 4> UninitializedFields;
+
+ // At the beginning, all fields are uninitialized.
+ for (DeclContext::decl_iterator I = RD->decls_begin(), E = RD->decls_end();
+ I != E; ++I) {
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(*I)) {
+ UninitializedFields.insert(FD);
+ } else if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(*I)) {
+ UninitializedFields.insert(IFD->getAnonField());
+ }
+ }
+
+ for (CXXConstructorDecl::init_const_iterator FieldInit =
+ Constructor->init_begin(),
+ FieldInitEnd = Constructor->init_end();
+ FieldInit != FieldInitEnd; ++FieldInit) {
+
+ Expr *InitExpr = (*FieldInit)->getInit();
+
+ CheckInitExprContainsUninitializedFields(
+ SemaRef, InitExpr, UninitializedFields, Constructor);
+
+ if (FieldDecl *Field = (*FieldInit)->getAnyMember())
+ UninitializedFields.erase(Field);
+ }
}
} // namespace
@@ -2146,17 +2354,8 @@ Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc,
return;
}
- if (getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit, InitLoc)
- != DiagnosticsEngine::Ignored) {
- CheckInitExprContainsUninitializedFields(*this, InitExpr, FD);
- }
-
ExprResult Init = InitExpr;
if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
- if (isa<InitListExpr>(InitExpr) && isStdInitializerList(FD->getType(), 0)) {
- Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list)
- << /*at end of ctor*/1 << InitExpr->getSourceRange();
- }
InitializedEntity Entity = InitializedEntity::InitializeMember(FD);
InitializationKind Kind = FD->getInClassInitStyle() == ICIS_ListInit
? InitializationKind::CreateDirectList(InitExpr->getLocStart())
@@ -2254,12 +2453,11 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
const DeclSpec &DS,
SourceLocation IdLoc,
SourceLocation LParenLoc,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr *> Args,
SourceLocation RParenLoc,
SourceLocation EllipsisLoc) {
Expr *List = new (Context) ParenListExpr(Context, LParenLoc,
- llvm::makeArrayRef(Args, NumArgs),
- RParenLoc);
+ Args, RParenLoc);
return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
DS, IdLoc, List, EllipsisLoc);
}
@@ -2269,21 +2467,20 @@ namespace {
// Callback to only accept typo corrections that can be a valid C++ member
// intializer: either a non-static field member or a base class.
class MemInitializerValidatorCCC : public CorrectionCandidateCallback {
- public:
+public:
explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl)
: ClassDecl(ClassDecl) {}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) LLVM_OVERRIDE {
if (NamedDecl *ND = candidate.getCorrectionDecl()) {
if (FieldDecl *Member = dyn_cast<FieldDecl>(ND))
return Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl);
- else
- return isa<TypeDecl>(ND);
+ return isa<TypeDecl>(ND);
}
return false;
}
- private:
+private:
CXXRecordDecl *ClassDecl;
};
@@ -2389,18 +2586,13 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
if (R.empty() && BaseType.isNull() &&
(Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
Validator, ClassDecl))) {
- std::string CorrectedStr(Corr.getAsString(getLangOpts()));
- std::string CorrectedQuotedStr(Corr.getQuoted(getLangOpts()));
if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) {
// We have found a non-static data member with a similar
// name to what was typed; complain and initialize that
// member.
- Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
- << MemberOrBase << true << CorrectedQuotedStr
- << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
- Diag(Member->getLocation(), diag::note_previous_decl)
- << CorrectedQuotedStr;
-
+ diagnoseTypo(Corr,
+ PDiag(diag::err_mem_init_not_member_or_class_suggest)
+ << MemberOrBase << true);
return BuildMemberInitializer(Member, Init, IdLoc);
} else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) {
const CXXBaseSpecifier *DirectBaseSpec;
@@ -2411,12 +2603,13 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
// We have found a direct or virtual base class with a
// similar name to what was typed; complain and initialize
// that base class.
- Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
- << MemberOrBase << false << CorrectedQuotedStr
- << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
+ diagnoseTypo(Corr,
+ PDiag(diag::err_mem_init_not_member_or_class_suggest)
+ << MemberOrBase << false,
+ PDiag() /*Suppress note, we provide our own.*/);
- const CXXBaseSpecifier *BaseSpec = DirectBaseSpec? DirectBaseSpec
- : VirtualBaseSpec;
+ const CXXBaseSpecifier *BaseSpec = DirectBaseSpec ? DirectBaseSpec
+ : VirtualBaseSpec;
Diag(BaseSpec->getLocStart(),
diag::note_base_class_specified_here)
<< BaseSpec->getType()
@@ -2480,15 +2673,7 @@ static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member,
}
}
- if (isa<MaterializeTemporaryExpr>(Init->IgnoreParens())) {
- // Taking the address of a temporary will be diagnosed as a hard error.
- if (IsPointer)
- return;
-
- S.Diag(Init->getExprLoc(), diag::warn_bind_ref_member_to_temporary)
- << Member << Init->getSourceRange();
- } else if (const DeclRefExpr *DRE
- = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) {
+ 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())
@@ -2521,10 +2706,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
if (Member->isInvalidDecl())
return true;
- // Diagnose value-uses of fields to initialize themselves, e.g.
- // foo(foo)
- // where foo is not also a parameter to the constructor.
- // TODO: implement -Wuninitialized and fold this into that framework.
MultiExprArg Args;
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs());
@@ -2535,19 +2716,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
Args = Init;
}
- if (getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit, IdLoc)
- != DiagnosticsEngine::Ignored)
- for (unsigned i = 0, e = Args.size(); i != e; ++i)
- // FIXME: Warn about the case when other fields are used before being
- // initialized. For example, let this field be the i'th field. When
- // initializing the i'th field, throw a warning if any of the >= i'th
- // fields are used, as they are not yet initialized.
- // Right now we are only handling the case where the i'th field uses
- // itself in its initializer.
- // Also need to take into account that some fields may be initialized by
- // in-class initializers, see C++11 [class.base.init]p9.
- CheckInitExprContainsUninitializedFields(*this, Args[i], Member);
-
SourceRange InitRange = Init->getSourceRange();
if (Member->getType()->isDependentType() || Init->isTypeDependent()) {
@@ -2559,11 +2727,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
if (isa<InitListExpr>(Init)) {
InitList = true;
Args = Init;
-
- if (isStdInitializerList(Member->getType(), 0)) {
- Diag(IdLoc, diag::warn_dangling_std_initializer_list)
- << /*at end of ctor*/1 << InitRange;
- }
}
// Initialize the member.
@@ -2580,6 +2743,8 @@ 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.
@@ -2588,7 +2753,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
return true;
Init = MemberInit.get();
- CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc);
}
if (DirectMember) {
@@ -2742,9 +2906,9 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
<< BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();
- CXXBaseSpecifier *BaseSpec = const_cast<CXXBaseSpecifier *>(DirectBaseSpec);
+ const CXXBaseSpecifier *BaseSpec = DirectBaseSpec;
if (!BaseSpec)
- BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec);
+ BaseSpec = VirtualBaseSpec;
// Initialize the base.
bool InitList = true;
@@ -3228,6 +3392,8 @@ static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) {
static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
FieldDecl *Field,
IndirectFieldDecl *Indirect = 0) {
+ if (Field->isInvalidDecl())
+ return false;
// Overwhelmingly common case: we have a direct initializer for this field.
if (CXXCtorInitializer *Init = Info.AllBaseFields.lookup(Field))
@@ -3266,7 +3432,7 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
// Don't try to build an implicit initializer if there were semantic
// errors in any of the initializers (and therefore we might be
// missing some that the user actually wrote).
- if (Info.AnyErrorsInInits || Field->isInvalidDecl())
+ if (Info.AnyErrorsInInits)
return false;
CXXCtorInitializer *Init = 0;
@@ -3333,7 +3499,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
for (unsigned i = 0; i < Initializers.size(); i++) {
CXXCtorInitializer *Member = Initializers[i];
-
+
if (Member->isBaseInitializer())
Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
else
@@ -3354,12 +3520,28 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
if (CXXCtorInitializer *Value
= Info.AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
+ // [class.base.init]p7, per DR257:
+ // A mem-initializer where the mem-initializer-id names a virtual base
+ // class is ignored during execution of a constructor of any class that
+ // is not the most derived class.
+ if (ClassDecl->isAbstract()) {
+ // FIXME: Provide a fixit to remove the base specifier. This requires
+ // tracking the location of the associated comma for a base specifier.
+ Diag(Value->getSourceLocation(), diag::warn_abstract_vbase_init_ignored)
+ << VBase->getType() << ClassDecl;
+ DiagnoseAbstractType(ClassDecl);
+ }
+
Info.AllToInit.push_back(Value);
- } else if (!AnyErrors) {
+ } else if (!AnyErrors && !ClassDecl->isAbstract()) {
+ // [class.base.init]p8, per DR257:
+ // If a given [...] base class is not named by a mem-initializer-id
+ // [...] and the entity is not a virtual base class of an abstract
+ // class, then [...] the entity is default-initialized.
bool IsInheritedVirtualBase = !DirectVBases.count(VBase);
CXXCtorInitializer *CXXBaseInit;
if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
- VBase, IsInheritedVirtualBase,
+ VBase, IsInheritedVirtualBase,
CXXBaseInit)) {
HadError = true;
continue;
@@ -3465,12 +3647,12 @@ static void PopulateKeysForFields(FieldDecl *Field, SmallVectorImpl<const void*>
IdealInits.push_back(Field);
}
-static void *GetKeyForBase(ASTContext &Context, QualType BaseType) {
- return const_cast<Type*>(Context.getCanonicalType(BaseType).getTypePtr());
+static const void *GetKeyForBase(ASTContext &Context, QualType BaseType) {
+ return Context.getCanonicalType(BaseType).getTypePtr();
}
-static void *GetKeyForMember(ASTContext &Context,
- CXXCtorInitializer *Member) {
+static const void *GetKeyForMember(ASTContext &Context,
+ CXXCtorInitializer *Member) {
if (!Member->isAnyMemberInitializer())
return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0));
@@ -3534,7 +3716,7 @@ static void DiagnoseBaseOrMemInitializerOrder(
CXXCtorInitializer *PrevInit = 0;
for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) {
CXXCtorInitializer *Init = Inits[InitIndex];
- void *InitKey = GetKeyForMember(SemaRef.Context, Init);
+ const void *InitKey = GetKeyForMember(SemaRef.Context, Init);
// Scan forward to try to find this initializer in the idealized
// initializers list.
@@ -3660,7 +3842,7 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
// Mapping for the duplicate initializers check.
// For member initializers, this is keyed with a FieldDecl*.
// For base initializers, this is keyed with a Type*.
- llvm::DenseMap<void*, CXXCtorInitializer *> Members;
+ llvm::DenseMap<const void *, CXXCtorInitializer *> Members;
// Mapping for the inconsistent anonymous-union initializers check.
RedundantUnionMap MemberUnions;
@@ -3678,7 +3860,8 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
CheckRedundantUnionInit(*this, Init, MemberUnions))
HadError = true;
} else if (Init->isBaseInitializer()) {
- void *Key = GetKeyForBase(Context, QualType(Init->getBaseClass(), 0));
+ const void *Key =
+ GetKeyForBase(Context, QualType(Init->getBaseClass(), 0));
if (CheckRedundantInit(*this, Init, Members[Key]))
HadError = true;
} else {
@@ -3702,6 +3885,8 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits);
SetCtorInitializers(Constructor, AnyErrors, MemInits);
+
+ DiagnoseUninitializedFields(*this, Constructor);
}
void
@@ -3750,7 +3935,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
<< Field->getDeclName()
<< FieldType);
- MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+ MarkFunctionReferenced(Location, Dtor);
DiagnoseUseOfDecl(Dtor, Location);
}
@@ -3783,7 +3968,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
<< Base->getSourceRange(),
Context.getTypeDeclType(ClassDecl));
- MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+ MarkFunctionReferenced(Location, Dtor);
DiagnoseUseOfDecl(Dtor, Location);
}
@@ -3807,12 +3992,19 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
assert(Dtor && "No dtor found for BaseClassDecl!");
- CheckDestructorAccess(ClassDecl->getLocation(), Dtor,
- PDiag(diag::err_access_dtor_vbase)
- << VBase->getType(),
- Context.getTypeDeclType(ClassDecl));
-
- MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+ if (CheckDestructorAccess(
+ ClassDecl->getLocation(), Dtor,
+ PDiag(diag::err_access_dtor_vbase)
+ << Context.getTypeDeclType(ClassDecl) << VBase->getType(),
+ Context.getTypeDeclType(ClassDecl)) ==
+ AR_accessible) {
+ CheckDerivedToBaseConversion(
+ Context.getTypeDeclType(ClassDecl), VBase->getType(),
+ diag::err_access_dtor_vbase, 0, ClassDecl->getLocation(),
+ SourceRange(), DeclarationName(), 0);
+ }
+
+ MarkFunctionReferenced(Location, Dtor);
DiagnoseUseOfDecl(Dtor, Location);
}
}
@@ -3822,8 +4014,10 @@ void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) {
return;
if (CXXConstructorDecl *Constructor
- = dyn_cast<CXXConstructorDecl>(CDtorDecl))
+ = dyn_cast<CXXConstructorDecl>(CDtorDecl)) {
SetCtorInitializers(Constructor, /*AnyErrors=*/false);
+ DiagnoseUninitializedFields(*this, Constructor);
+ }
}
bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
@@ -3835,8 +4029,8 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
public:
NonAbstractTypeDiagnoser(unsigned DiagID, AbstractDiagSelID SelID)
: TypeDiagnoser(DiagID == 0), DiagID(DiagID), SelID(SelID) { }
-
- virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) LLVM_OVERRIDE {
if (Suppressed) return;
if (SelID == -1)
S.Diag(Loc, DiagID) << T;
@@ -3893,6 +4087,12 @@ void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) {
if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD))
return;
+ // If the diagnostic is suppressed, don't emit the notes. We're only
+ // going to emit them once, so try to attach them to a diagnostic we're
+ // actually going to show.
+ if (Diags.isLastDiagnosticIgnored())
+ return;
+
CXXFinalOverriderMap FinalOverriders;
RD->getFinalOverriders(FinalOverriders);
@@ -4172,9 +4372,12 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
diag::warn_non_virtual_dtor) << Context.getRecordType(Record);
}
- if (Record->isAbstract() && Record->hasAttr<FinalAttr>()) {
- Diag(Record->getLocation(), diag::warn_abstract_final_class);
- DiagnoseAbstractType(Record);
+ if (Record->isAbstract()) {
+ if (FinalAttr *FA = Record->getAttr<FinalAttr>()) {
+ Diag(Record->getLocation(), diag::warn_abstract_final_class)
+ << FA->isSpelledAsSealed();
+ DiagnoseAbstractType(Record);
+ }
}
if (!Record->isDependentType()) {
@@ -4184,7 +4387,7 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
// See if a method overloads virtual methods in a base
// class without overriding any.
if (!M->isStatic())
- DiagnoseHiddenVirtualMethods(Record, *M);
+ DiagnoseHiddenVirtualMethods(*M);
// Check whether the explicitly-defaulted special members are valid.
if (!M->isInvalidDecl() && M->isExplicitlyDefaulted())
@@ -4243,6 +4446,13 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
}
+ // Check to see if we're trying to lay out a struct using the ms_struct
+ // attribute that is dynamic.
+ if (Record->isMsStruct(Context) && Record->isDynamicClass()) {
+ Diag(Record->getLocation(), diag::warn_pragma_ms_struct_failed);
+ Record->dropAttr<MsStructAttr>();
+ }
+
// Declare inheriting constructors. We do this eagerly here because:
// - The standard requires an eager diagnostic for conflicting inheriting
// constructors from different classes.
@@ -4278,6 +4488,7 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
// C++11 [dcl.constexpr]p4:
// In the definition of a constexpr constructor [...]
+ bool Ctor = true;
switch (CSM) {
case Sema::CXXDefaultConstructor:
// Since default constructor lookup is essentially trivial (and cannot
@@ -4295,6 +4506,12 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
case Sema::CXXCopyAssignment:
case Sema::CXXMoveAssignment:
+ if (!S.getLangOpts().CPlusPlus1y)
+ return false;
+ // In C++1y, we need to perform overload resolution.
+ Ctor = false;
+ break;
+
case Sema::CXXDestructor:
case Sema::CXXInvalid:
return false;
@@ -4307,15 +4524,22 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
// If we squint, this is guaranteed, since exactly one non-static data member
// will be initialized (if the constructor isn't deleted), we just don't know
// which one.
- if (ClassDecl->isUnion())
+ if (Ctor && ClassDecl->isUnion())
return true;
// -- the class shall not have any virtual base classes;
- if (ClassDecl->getNumVBases())
+ if (Ctor && ClassDecl->getNumVBases())
+ return false;
+
+ // C++1y [class.copy]p26:
+ // -- [the class] is a literal type, and
+ if (!Ctor && !ClassDecl->isLiteral())
return false;
// -- every constructor involved in initializing [...] base class
// sub-objects shall be a constexpr constructor;
+ // -- the assignment operator selected to copy/move each direct base
+ // class is a constexpr function, and
for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
BEnd = ClassDecl->bases_end();
B != BEnd; ++B) {
@@ -4331,6 +4555,9 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
// [...] shall be a constexpr constructor;
// -- every non-static data member and base class sub-object shall be
// initialized
+ // -- for each non-stastic data member of X that is of class type (or array
+ // thereof), the assignment operator selected to copy/move that member is
+ // a constexpr function
for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
FEnd = ClassDecl->field_end();
F != FEnd; ++F) {
@@ -4380,6 +4607,21 @@ updateExceptionSpec(Sema &S, FunctionDecl *FD, const FunctionProtoType *FPT,
FPT->getArgTypes(), EPI));
}
+static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S,
+ CXXMethodDecl *MD) {
+ FunctionProtoType::ExtProtoInfo EPI;
+
+ // Build an exception specification pointing back at this member.
+ EPI.ExceptionSpecType = EST_Unevaluated;
+ EPI.ExceptionSpecDecl = MD;
+
+ // Set the calling convention to the default for C++ instance methods.
+ EPI.ExtInfo = EPI.ExtInfo.withCallingConv(
+ S.Context.getDefaultCallingConvention(/*IsVariadic=*/false,
+ /*IsCXXMethod=*/true));
+ return EPI;
+}
+
void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD) {
const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
if (FPT->getExceptionSpecType() != EST_Unevaluated)
@@ -4461,7 +4703,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
// A defaulted special member cannot have cv-qualifiers.
if (Type->getTypeQuals()) {
Diag(MD->getLocation(), diag::err_defaulted_special_member_quals)
- << (CSM == CXXMoveAssignment);
+ << (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus1y;
HadError = true;
}
}
@@ -4506,13 +4748,16 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
// would have been implicitly declared as constexpr,
// Do not apply this rule to members of class templates, since core issue 1358
// makes such functions always instantiate to constexpr functions. For
- // non-constructors, this is checked elsewhere.
+ // functions which cannot be constexpr (for non-constructors in C++11 and for
+ // destructors in C++1y), this is checked elsewhere.
bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, RD, CSM,
HasConstParam);
- if (isa<CXXConstructorDecl>(MD) && MD->isConstexpr() && !Constexpr &&
+ if ((getLangOpts().CPlusPlus1y ? !isa<CXXDestructorDecl>(MD)
+ : isa<CXXConstructorDecl>(MD)) &&
+ MD->isConstexpr() && !Constexpr &&
MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
Diag(MD->getLocStart(), diag::err_incorrect_defaulted_constexpr) << CSM;
- // FIXME: Explain why the constructor can't be constexpr.
+ // FIXME: Explain why the special member can't be constexpr.
HadError = true;
}
@@ -4573,7 +4818,9 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
void Sema::CheckExplicitlyDefaultedMemberExceptionSpec(
CXXMethodDecl *MD, const FunctionProtoType *SpecifiedType) {
// Compute the implicit exception specification.
- FunctionProtoType::ExtProtoInfo EPI;
+ CallingConv CC = Context.getDefaultCallingConvention(/*IsVariadic=*/false,
+ /*IsCXXMethod=*/true);
+ FunctionProtoType::ExtProtoInfo EPI(CC);
computeImplicitExceptionSpec(*this, MD->getLocation(), MD).getEPI(EPI);
const FunctionProtoType *ImplicitType = cast<FunctionProtoType>(
Context.getFunctionType(Context.VoidTy, None, EPI));
@@ -4586,14 +4833,28 @@ void Sema::CheckExplicitlyDefaultedMemberExceptionSpec(
SpecifiedType, MD->getLocation());
}
-void Sema::CheckDelayedExplicitlyDefaultedMemberExceptionSpecs() {
- for (unsigned I = 0, N = DelayedDefaultedMemberExceptionSpecs.size();
- I != N; ++I)
- CheckExplicitlyDefaultedMemberExceptionSpec(
- DelayedDefaultedMemberExceptionSpecs[I].first,
- DelayedDefaultedMemberExceptionSpecs[I].second);
+void Sema::CheckDelayedMemberExceptionSpecs() {
+ SmallVector<std::pair<const CXXDestructorDecl *, const CXXDestructorDecl *>,
+ 2> Checks;
+ SmallVector<std::pair<CXXMethodDecl *, const FunctionProtoType *>, 2> Specs;
- DelayedDefaultedMemberExceptionSpecs.clear();
+ std::swap(Checks, DelayedDestructorExceptionSpecChecks);
+ std::swap(Specs, DelayedDefaultedMemberExceptionSpecs);
+
+ // Perform any deferred checking of exception specifications for virtual
+ // destructors.
+ for (unsigned i = 0, e = Checks.size(); i != e; ++i) {
+ const CXXDestructorDecl *Dtor = Checks[i].first;
+ assert(!Dtor->getParent()->isDependentType() &&
+ "Should not ever add destructors of templates into the list.");
+ CheckOverridingFunctionExceptionSpec(Dtor, Checks[i].second);
+ }
+
+ // Check that any explicitly-defaulted methods have exception specifications
+ // compatible with their implicit exception specifications.
+ for (unsigned I = 0, N = Specs.size(); I != N; ++I)
+ CheckExplicitlyDefaultedMemberExceptionSpec(Specs[I].first,
+ Specs[I].second);
}
namespace {
@@ -4652,6 +4913,10 @@ struct SpecialMemberDeletionInfo {
// cv-qualifiers on class members don't affect default ctor / dtor calls.
if (CSM == Sema::CXXDefaultConstructor || CSM == Sema::CXXDestructor)
Quals = 0;
+ // cv-qualifiers on class members affect the type of both '*this' and the
+ // argument for an assignment.
+ if (IsAssignment)
+ TQ |= Quals;
return S.LookupSpecialMember(Class, CSM,
ConstArg || (Quals & Qualifiers::Const),
VolatileArg || (Quals & Qualifiers::Volatile),
@@ -5015,10 +5280,15 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
SMI.shouldDeleteForBase(BI))
return true;
- for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(),
- BE = RD->vbases_end(); BI != BE; ++BI)
- if (SMI.shouldDeleteForBase(BI))
- return true;
+ // Per DR1611, do not consider virtual bases of constructors of abstract
+ // classes, since we are not going to construct them.
+ if (!RD->isAbstract() || !SMI.IsConstructor) {
+ for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(),
+ BE = RD->vbases_end();
+ BI != BE; ++BI)
+ if (SMI.shouldDeleteForBase(BI))
+ return true;
+ }
for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
FE = RD->field_end(); FI != FE; ++FI)
@@ -5310,9 +5580,9 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
bool ConstArg = false;
- // C++11 [class.copy]p12, p25:
- // A [special member] is trivial if its declared parameter type is the same
- // as if it had been implicitly declared [...]
+ // C++11 [class.copy]p12, p25: [DR1593]
+ // A [special member] is trivial if [...] its parameter-type-list is
+ // equivalent to the parameter-type-list of an implicit declaration [...]
switch (CSM) {
case CXXDefaultConstructor:
case CXXDestructor:
@@ -5356,11 +5626,6 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
llvm_unreachable("not a special member");
}
- // FIXME: We require that the parameter-declaration-clause is equivalent to
- // that of an implicit declaration, not just that the declared parameter type
- // matches, in order to prevent absuridities like a function simultaneously
- // being a trivial copy constructor and a non-trivial default constructor.
- // This issue has not yet been assigned a core issue number.
if (MD->getMinRequiredArguments() < MD->getNumParams()) {
if (Diagnose)
Diag(MD->getParamDecl(MD->getMinRequiredArguments())->getLocation(),
@@ -5524,12 +5789,10 @@ static void AddMostOverridenMethods(const CXXMethodDecl *MD,
AddMostOverridenMethods(*I, Methods);
}
-/// \brief See if a method overloads virtual methods in a base class without
+/// \brief Check if a method overloads virtual methods in a base class without
/// overriding any.
-void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
- if (Diags.getDiagnosticLevel(diag::warn_overloaded_virtual,
- MD->getLocation()) == DiagnosticsEngine::Ignored)
- return;
+void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD,
+ SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) {
if (!MD->getDeclName().isIdentifier())
return;
@@ -5542,6 +5805,7 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
// Keep the base methods that were overriden or introduced in the subclass
// by 'using' in a set. A base method not in this set is hidden.
+ CXXRecordDecl *DC = MD->getParent();
DeclContext::lookup_result R = DC->lookup(MD->getDeclName());
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) {
NamedDecl *ND = *I;
@@ -5551,18 +5815,38 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
AddMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods);
}
- if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths) &&
- !Data.OverloadedMethods.empty()) {
+ if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths))
+ OverloadedMethods = Data.OverloadedMethods;
+}
+
+void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD,
+ SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) {
+ for (unsigned i = 0, e = OverloadedMethods.size(); i != e; ++i) {
+ CXXMethodDecl *overloadedMD = OverloadedMethods[i];
+ PartialDiagnostic PD = PDiag(
+ diag::note_hidden_overloaded_virtual_declared_here) << overloadedMD;
+ HandleFunctionTypeMismatch(PD, MD->getType(), overloadedMD->getType());
+ Diag(overloadedMD->getLocation(), PD);
+ }
+}
+
+/// \brief Diagnose methods which overload virtual methods in a base class
+/// without overriding any.
+void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) {
+ if (MD->isInvalidDecl())
+ return;
+
+ if (Diags.getDiagnosticLevel(diag::warn_overloaded_virtual,
+ MD->getLocation()) == DiagnosticsEngine::Ignored)
+ return;
+
+ SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
+ FindHiddenVirtualMethods(MD, OverloadedMethods);
+ if (!OverloadedMethods.empty()) {
Diag(MD->getLocation(), diag::warn_overloaded_virtual)
- << MD << (Data.OverloadedMethods.size() > 1);
+ << MD << (OverloadedMethods.size() > 1);
- for (unsigned i = 0, e = Data.OverloadedMethods.size(); i != e; ++i) {
- CXXMethodDecl *overloadedMD = Data.OverloadedMethods[i];
- PartialDiagnostic PD = PDiag(
- diag::note_hidden_overloaded_virtual_declared_here) << overloadedMD;
- HandleFunctionTypeMismatch(PD, MD->getType(), overloadedMD->getType());
- Diag(overloadedMD->getLocation(), PD);
- }
+ NoteHiddenVirtualMethods(MD, OverloadedMethods);
}
}
@@ -5877,7 +6161,7 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
CXXRecordDecl *RD = Destructor->getParent();
- if (Destructor->isVirtual()) {
+ if (!Destructor->getOperatorDelete() && Destructor->isVirtual()) {
SourceLocation Loc;
if (!Destructor->isImplicit())
@@ -5891,6 +6175,10 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
Context.DeclarationNames.getCXXOperatorName(OO_Delete);
if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
return true;
+ // If there's no class-specific operator delete, look up the global
+ // non-array delete.
+ if (!OperatorDelete)
+ OperatorDelete = FindUsualDeallocationFunction(Loc, true, Name);
MarkFunctionReferenced(Loc, OperatorDelete);
@@ -6029,8 +6317,8 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
if (SC == SC_Static) {
if (!D.isInvalidType())
Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member)
- << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
- << SourceRange(D.getIdentifierLoc());
+ << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
+ << D.getName().getSourceRange();
D.setInvalidType();
SC = SC_None;
}
@@ -6541,11 +6829,10 @@ namespace {
// Callback to only accept typo corrections that are namespaces.
class NamespaceValidatorCCC : public CorrectionCandidateCallback {
- public:
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
- if (NamedDecl *ND = candidate.getCorrectionDecl()) {
+public:
+ bool ValidateCandidate(const TypoCorrection &candidate) LLVM_OVERRIDE {
+ if (NamedDecl *ND = candidate.getCorrectionDecl())
return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
- }
return false;
}
};
@@ -6561,21 +6848,19 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(),
R.getLookupKind(), Sc, &SS,
Validator)) {
- std::string CorrectedStr(Corrected.getAsString(S.getLangOpts()));
- std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOpts()));
- if (DeclContext *DC = S.computeDeclContext(SS, false))
- S.Diag(IdentLoc, diag::err_using_directive_member_suggest)
- << Ident << DC << CorrectedQuotedStr << SS.getRange()
- << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
- CorrectedStr);
- else
- S.Diag(IdentLoc, diag::err_using_directive_suggest)
- << Ident << CorrectedQuotedStr
- << FixItHint::CreateReplacement(IdentLoc, CorrectedStr);
-
- S.Diag(Corrected.getCorrectionDecl()->getLocation(),
- diag::note_namespace_defined_here) << CorrectedQuotedStr;
-
+ if (DeclContext *DC = S.computeDeclContext(SS, false)) {
+ std::string CorrectedStr(Corrected.getAsString(S.getLangOpts()));
+ bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
+ Ident->getName().equals(CorrectedStr);
+ S.diagnoseTypo(Corrected,
+ S.PDiag(diag::err_using_directive_member_suggest)
+ << Ident << DC << DroppedSpecifier << SS.getRange(),
+ S.PDiag(diag::note_namespace_defined_here));
+ } else {
+ S.diagnoseTypo(Corrected,
+ S.PDiag(diag::err_using_directive_suggest) << Ident,
+ S.PDiag(diag::note_namespace_defined_here));
+ }
R.addDecl(Corrected.getCorrectionDecl());
return true;
}
@@ -6649,7 +6934,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
IdentLoc, Named, CommonAncestor);
if (IsUsingDirectiveInToplevelContext(CurContext) &&
- !SourceMgr.isFromMainFile(SourceMgr.getExpansionLoc(IdentLoc))) {
+ !SourceMgr.isInMainFile(SourceMgr.getExpansionLoc(IdentLoc))) {
Diag(IdentLoc, diag::warn_using_directive_in_header);
}
@@ -6668,7 +6953,7 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
// If the scope has an associated entity and the using directive is at
// namespace or translation unit scope, add the UsingDirectiveDecl into
// its lookup structure so qualified name lookup can find it.
- DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
+ DeclContext *Ctx = S->getEntity();
if (Ctx && !Ctx->isFunctionOrMethod())
Ctx->addDecl(UDir);
else
@@ -6685,7 +6970,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
CXXScopeSpec &SS,
UnqualifiedId &Name,
AttributeList *AttrList,
- bool IsTypeName,
+ bool HasTypenameKeyword,
SourceLocation TypenameLoc) {
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
@@ -6727,13 +7012,10 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
return 0;
// Warn about access declarations.
- // TODO: store that the declaration was written without 'using' and
- // talk about access decls instead of using decls in the
- // diagnostics.
if (!HasUsingKeyword) {
- UsingLoc = Name.getLocStart();
-
- Diag(UsingLoc, diag::warn_access_decl_deprecated)
+ Diag(Name.getLocStart(),
+ getLangOpts().CPlusPlus11 ? diag::err_access_decl
+ : diag::warn_access_decl_deprecated)
<< FixItHint::CreateInsertion(SS.getRange().getBegin(), "using ");
}
@@ -6744,7 +7026,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
TargetNameInfo, AttrList,
/* IsInstantiation */ false,
- IsTypeName, TypenameLoc);
+ HasTypenameKeyword, TypenameLoc);
if (UD)
PushOnScopeChains(UD, S, /*AddToContext*/ false);
@@ -6754,20 +7036,15 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
/// \brief 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
-IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2,
- bool &SuppressRedeclaration) {
- if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) {
- SuppressRedeclaration = false;
+static bool
+IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2) {
+ if (D1->getCanonicalDecl() == D2->getCanonicalDecl())
return true;
- }
if (TypedefNameDecl *TD1 = dyn_cast<TypedefNameDecl>(D1))
- if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2)) {
- SuppressRedeclaration = true;
+ if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2))
return Context.hasSameType(TD1->getUnderlyingType(),
TD2->getUnderlyingType());
- }
return false;
}
@@ -6776,7 +7053,8 @@ IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2,
/// Determines whether to create a using shadow decl for a particular
/// decl, given the set of decls existing prior to this using lookup.
bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
- const LookupResult &Previous) {
+ const LookupResult &Previous,
+ UsingShadowDecl *&PrevShadow) {
// Diagnose finding a decl which is not from a base class of the
// current class. We do this now because there are cases where this
// function will silently decide not to build a shadow decl, which
@@ -6836,16 +7114,22 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
// FIXME: but we might be increasing its access, in which case we
// should redeclare it.
NamedDecl *NonTag = 0, *Tag = 0;
+ bool FoundEquivalentDecl = false;
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
I != E; ++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
- bool Result;
- if (IsEquivalentForUsingDecl(Context, D, Target, Result))
- return Result;
+ if (IsEquivalentForUsingDecl(Context, D, Target)) {
+ if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I))
+ PrevShadow = Shadow;
+ FoundEquivalentDecl = true;
+ }
(isa<TagDecl>(D) ? Tag : NonTag) = D;
}
+ if (FoundEquivalentDecl)
+ return false;
+
if (Target->isFunctionOrFunctionTemplate()) {
FunctionDecl *FD;
if (isa<FunctionTemplateDecl>(Target))
@@ -6904,7 +7188,8 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
/// Builds a shadow declaration corresponding to a 'using' declaration.
UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
UsingDecl *UD,
- NamedDecl *Orig) {
+ NamedDecl *Orig,
+ UsingShadowDecl *PrevDecl) {
// If we resolved to another shadow declaration, just coalesce them.
NamedDecl *Target = Orig;
@@ -6912,16 +7197,18 @@ UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
Target = cast<UsingShadowDecl>(Target)->getTargetDecl();
assert(!isa<UsingShadowDecl>(Target) && "nested shadow declaration");
}
-
+
UsingShadowDecl *Shadow
= UsingShadowDecl::Create(Context, CurContext,
UD->getLocation(), UD, Target);
UD->addShadowDecl(Shadow);
-
+
Shadow->setAccess(UD->getAccess());
if (Orig->isInvalidDecl() || UD->isInvalidDecl())
Shadow->setInvalidDecl();
-
+
+ Shadow->setPreviousDecl(PrevDecl);
+
if (S)
PushOnScopeChains(Shadow, S);
else
@@ -6979,6 +7266,42 @@ void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) {
// be possible for this to happen, because...?
}
+namespace {
+class UsingValidatorCCC : public CorrectionCandidateCallback {
+public:
+ UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation,
+ bool RequireMember)
+ : HasTypenameKeyword(HasTypenameKeyword),
+ IsInstantiation(IsInstantiation), RequireMember(RequireMember) {}
+
+ bool ValidateCandidate(const TypoCorrection &Candidate) LLVM_OVERRIDE {
+ NamedDecl *ND = Candidate.getCorrectionDecl();
+
+ // Keywords are not valid here.
+ if (!ND || isa<NamespaceDecl>(ND))
+ return false;
+
+ if (RequireMember && !isa<FieldDecl>(ND) && !isa<CXXMethodDecl>(ND) &&
+ !isa<TypeDecl>(ND))
+ return false;
+
+ // Completely unqualified names are invalid for a 'using' declaration.
+ if (Candidate.WillReplaceSpecifier() && !Candidate.getCorrectionSpecifier())
+ return false;
+
+ if (isa<TypeDecl>(ND))
+ return HasTypenameKeyword || !IsInstantiation;
+
+ return !HasTypenameKeyword;
+ }
+
+private:
+ bool HasTypenameKeyword;
+ bool IsInstantiation;
+ bool RequireMember;
+};
+} // end anonymous namespace
+
/// Builds a using declaration.
///
/// \param IsInstantiation - Whether this call arises from an
@@ -6990,7 +7313,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
const DeclarationNameInfo &NameInfo,
AttributeList *AttrList,
bool IsInstantiation,
- bool IsTypeName,
+ bool HasTypenameKeyword,
SourceLocation TypenameLoc) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
SourceLocation IdentLoc = NameInfo.getLoc();
@@ -7025,7 +7348,8 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
}
// Check for invalid redeclarations.
- if (CheckUsingDeclRedeclaration(UsingLoc, IsTypeName, SS, IdentLoc, Previous))
+ if (CheckUsingDeclRedeclaration(UsingLoc, HasTypenameKeyword,
+ SS, IdentLoc, Previous))
return 0;
// Check for bad qualifiers.
@@ -7036,7 +7360,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
NamedDecl *D;
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
if (!LookupContext) {
- if (IsTypeName) {
+ if (HasTypenameKeyword) {
// FIXME: not all declaration name kinds are legal here
D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
UsingLoc, TypenameLoc,
@@ -7048,7 +7372,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
}
} else {
D = UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc,
- NameInfo, IsTypeName);
+ NameInfo, HasTypenameKeyword);
}
D->setAccess(AS);
CurContext->addDecl(D);
@@ -7088,11 +7412,27 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
LookupQualifiedName(R, LookupContext);
+ // Try to correct typos if possible.
if (R.empty()) {
- Diag(IdentLoc, diag::err_no_member)
- << NameInfo.getName() << LookupContext << SS.getRange();
- UD->setInvalidDecl();
- return UD;
+ UsingValidatorCCC CCC(HasTypenameKeyword, IsInstantiation,
+ CurContext->isRecord());
+ if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
+ R.getLookupKind(), S, &SS, CCC)){
+ // We reject any correction for which ND would be NULL.
+ NamedDecl *ND = Corrected.getCorrectionDecl();
+ R.setLookupName(Corrected.getCorrection());
+ R.addDecl(ND);
+ // We reject candidates where DroppedSpecifier == true, hence the
+ // literal '0' below.
+ diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest)
+ << NameInfo.getName() << LookupContext << 0
+ << SS.getRange());
+ } else {
+ Diag(IdentLoc, diag::err_no_member)
+ << NameInfo.getName() << LookupContext << SS.getRange();
+ UD->setInvalidDecl();
+ return UD;
+ }
}
if (R.isAmbiguous()) {
@@ -7100,7 +7440,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
return UD;
}
- if (IsTypeName) {
+ if (HasTypenameKeyword) {
// If we asked for a typename and got a non-type decl, error out.
if (!R.getAsSingle<TypeDecl>()) {
Diag(IdentLoc, diag::err_using_typename_non_type);
@@ -7132,8 +7472,9 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
}
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
- if (!CheckUsingShadowDecl(UD, *I, Previous))
- BuildUsingShadowDecl(S, UD, *I);
+ UsingShadowDecl *PrevDecl = 0;
+ if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl))
+ BuildUsingShadowDecl(S, UD, *I, PrevDecl);
}
return UD;
@@ -7141,7 +7482,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
/// Additional checks for a using declaration referring to a constructor name.
bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
- assert(!UD->isTypeName() && "expecting a constructor name");
+ assert(!UD->hasTypename() && "expecting a constructor name");
const Type *SourceType = UD->getQualifier()->getAsType();
assert(SourceType &&
@@ -7162,7 +7503,7 @@ bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
if (BaseIt == BaseE) {
// Did not find SourceType in the bases.
- Diag(UD->getUsingLocation(),
+ Diag(UD->getUsingLoc(),
diag::err_using_decl_constructor_not_in_direct_base)
<< UD->getNameInfo().getSourceRange()
<< QualType(SourceType, 0) << TargetClass;
@@ -7179,7 +7520,7 @@ bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
/// redeclaration. Note that this is checking only for the using decl
/// itself, not for any ill-formedness among the UsingShadowDecls.
bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
- bool isTypeName,
+ bool HasTypenameKeyword,
const CXXScopeSpec &SS,
SourceLocation NameLoc,
const LookupResult &Prev) {
@@ -7202,7 +7543,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
bool DTypename;
NestedNameSpecifier *DQual;
if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
- DTypename = UD->isTypeName();
+ DTypename = UD->hasTypename();
DQual = UD->getQualifier();
} else if (UnresolvedUsingValueDecl *UD
= dyn_cast<UnresolvedUsingValueDecl>(D)) {
@@ -7216,7 +7557,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
// using decls differ if one says 'typename' and the other doesn't.
// FIXME: non-dependent using decls?
- if (isTypeName != DTypename) continue;
+ if (HasTypenameKeyword != DTypename) continue;
// using decls differ if they name different scopes (but note that
// template instantiation can cause this check to trigger when it
@@ -7498,7 +7839,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
if (Invalid)
NewDecl->setInvalidDecl();
else if (OldDecl)
- NewDecl->setPreviousDeclaration(OldDecl);
+ NewDecl->setPreviousDecl(OldDecl);
NewND = NewDecl;
} else {
@@ -7788,9 +8129,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
DefaultCon->setImplicit();
// Build an exception specification pointing back at this constructor.
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = DefaultCon;
+ FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, DefaultCon);
DefaultCon->setType(Context.getFunctionType(Context.VoidTy, None, EPI));
// We don't need to use SpecialMemberIsTrivial here; triviality for default
@@ -7833,18 +8172,19 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
SourceLocation Loc = Constructor->getLocation();
Constructor->setBody(new (Context) CompoundStmt(Loc));
- Constructor->setUsed();
+ Constructor->markUsed(Context);
MarkVTableUsed(CurrentLocation, ClassDecl);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Constructor);
}
+
+ DiagnoseUninitializedFields(*this, Constructor);
}
void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) {
- // Check that any explicitly-defaulted methods have exception specifications
- // compatible with their implicit exception specifications.
- CheckDelayedExplicitlyDefaultedMemberExceptionSpecs();
+ // Perform any delayed checks on exception specifications.
+ CheckDelayedMemberExceptionSpecs();
}
namespace {
@@ -7887,8 +8227,8 @@ private:
/// constructors.
struct InheritingConstructorsForType {
InheritingConstructor NonTemplate;
- llvm::SmallVector<
- std::pair<TemplateParameterList*, InheritingConstructor>, 4> Templates;
+ SmallVector<std::pair<TemplateParameterList *, InheritingConstructor>, 4>
+ Templates;
InheritingConstructor &getEntry(Sema &S, const CXXConstructorDecl *Ctor) {
if (FunctionTemplateDecl *FTD = Ctor->getDescribedFunctionTemplate()) {
@@ -8171,7 +8511,7 @@ void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation,
SourceLocation Loc = Constructor->getLocation();
Constructor->setBody(new (Context) CompoundStmt(Loc));
- Constructor->setUsed();
+ Constructor->markUsed(Context);
MarkVTableUsed(CurrentLocation, ClassDecl);
if (ASTMutationListener *L = getASTMutationListener()) {
@@ -8252,9 +8592,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
Destructor->setImplicit();
// Build an exception specification pointing back at this destructor.
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = Destructor;
+ FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, Destructor);
Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI));
AddOverriddenMethods(ClassDecl, Destructor);
@@ -8305,8 +8643,7 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
SourceLocation Loc = Destructor->getLocation();
Destructor->setBody(new (Context) CompoundStmt(Loc));
- Destructor->setImplicitlyDefined(true);
- Destructor->setUsed();
+ Destructor->markUsed(Context);
MarkVTableUsed(CurrentLocation, ClassDecl);
if (ASTMutationListener *L = getASTMutationListener()) {
@@ -8320,23 +8657,11 @@ void Sema::ActOnFinishCXXMemberDecls() {
// If the context is an invalid C++ class, just suppress these checks.
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(CurContext)) {
if (Record->isInvalidDecl()) {
+ DelayedDefaultedMemberExceptionSpecs.clear();
DelayedDestructorExceptionSpecChecks.clear();
return;
}
}
-
- // Perform any deferred checking of exception specifications for virtual
- // destructors.
- for (unsigned i = 0, e = DelayedDestructorExceptionSpecChecks.size();
- i != e; ++i) {
- const CXXDestructorDecl *Dtor =
- DelayedDestructorExceptionSpecChecks[i].first;
- assert(!Dtor->getParent()->isDependentType() &&
- "Should not ever add destructors of templates into the list.");
- CheckOverridingFunctionExceptionSpec(Dtor,
- DelayedDestructorExceptionSpecChecks[i].second);
- }
- DelayedDestructorExceptionSpecChecks.clear();
}
void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
@@ -8368,13 +8693,144 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
// needs to be done somewhere else.
}
+namespace {
+/// \brief 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 {
+ ExprBuilder(const ExprBuilder&) LLVM_DELETED_FUNCTION;
+ ExprBuilder &operator=(const ExprBuilder&) LLVM_DELETED_FUNCTION;
+
+protected:
+ static Expr *assertNotNull(Expr *E) {
+ assert(E && "Expression construction must not fail.");
+ return E;
+ }
+
+public:
+ ExprBuilder() {}
+ virtual ~ExprBuilder() {}
+
+ virtual Expr *build(Sema &S, SourceLocation Loc) const = 0;
+};
+
+class RefBuilder: public ExprBuilder {
+ VarDecl *Var;
+ QualType VarType;
+
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ return assertNotNull(S.BuildDeclRefExpr(Var, VarType, VK_LValue, Loc).take());
+ }
+
+ RefBuilder(VarDecl *Var, QualType VarType)
+ : Var(Var), VarType(VarType) {}
+};
+
+class ThisBuilder: public ExprBuilder {
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ return assertNotNull(S.ActOnCXXThis(Loc).takeAs<Expr>());
+ }
+};
+
+class CastBuilder: public ExprBuilder {
+ const ExprBuilder &Builder;
+ QualType Type;
+ ExprValueKind Kind;
+ const CXXCastPath &Path;
+
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ return assertNotNull(S.ImpCastExprToType(Builder.build(S, Loc), Type,
+ CK_UncheckedDerivedToBase, Kind,
+ &Path).take());
+ }
+
+ CastBuilder(const ExprBuilder &Builder, QualType Type, ExprValueKind Kind,
+ const CXXCastPath &Path)
+ : Builder(Builder), Type(Type), Kind(Kind), Path(Path) {}
+};
+
+class DerefBuilder: public ExprBuilder {
+ const ExprBuilder &Builder;
+
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ return assertNotNull(
+ S.CreateBuiltinUnaryOp(Loc, UO_Deref, Builder.build(S, Loc)).take());
+ }
+
+ DerefBuilder(const ExprBuilder &Builder) : Builder(Builder) {}
+};
+
+class MemberBuilder: public ExprBuilder {
+ const ExprBuilder &Builder;
+ QualType Type;
+ CXXScopeSpec SS;
+ bool IsArrow;
+ LookupResult &MemberLookup;
+
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ return assertNotNull(S.BuildMemberReferenceExpr(
+ Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(), 0,
+ MemberLookup, 0).take());
+ }
+
+ MemberBuilder(const ExprBuilder &Builder, QualType Type, bool IsArrow,
+ LookupResult &MemberLookup)
+ : Builder(Builder), Type(Type), IsArrow(IsArrow),
+ MemberLookup(MemberLookup) {}
+};
+
+class MoveCastBuilder: public ExprBuilder {
+ const ExprBuilder &Builder;
+
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ return assertNotNull(CastForMoving(S, Builder.build(S, Loc)));
+ }
+
+ MoveCastBuilder(const ExprBuilder &Builder) : Builder(Builder) {}
+};
+
+class LvalueConvBuilder: public ExprBuilder {
+ const ExprBuilder &Builder;
+
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ return assertNotNull(
+ S.DefaultLvalueConversion(Builder.build(S, Loc)).take());
+ }
+
+ LvalueConvBuilder(const ExprBuilder &Builder) : Builder(Builder) {}
+};
+
+class SubscriptBuilder: public ExprBuilder {
+ const ExprBuilder &Base;
+ const ExprBuilder &Index;
+
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const
+ LLVM_OVERRIDE {
+ return assertNotNull(S.CreateBuiltinArraySubscriptExpr(
+ Base.build(S, Loc), Loc, Index.build(S, Loc), Loc).take());
+ }
+
+ SubscriptBuilder(const ExprBuilder &Base, const ExprBuilder &Index)
+ : Base(Base), Index(Index) {}
+};
+
+} // end anonymous namespace
+
/// When generating a defaulted copy or move assignment operator, if a field
/// should be copied with __builtin_memcpy rather than via explicit assignments,
/// do so. This optimization only applies for arrays of scalars, and for arrays
/// of class type where the selected copy/move-assignment operator is trivial.
static StmtResult
buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
- Expr *To, Expr *From) {
+ const ExprBuilder &ToB, const ExprBuilder &FromB) {
// Compute the size of the memory buffer to be copied.
QualType SizeType = S.Context.getSizeType();
llvm::APInt Size(S.Context.getTypeSize(SizeType),
@@ -8383,9 +8839,11 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
// Take the address of the field references for "from" and "to". We
// directly construct UnaryOperators here because semantic analysis
// does not permit us to take the address of an xvalue.
+ Expr *From = FromB.build(S, Loc);
From = new (S.Context) UnaryOperator(From, UO_AddrOf,
S.Context.getPointerType(From->getType()),
VK_RValue, OK_Ordinary, Loc);
+ Expr *To = ToB.build(S, Loc);
To = new (S.Context) UnaryOperator(To, UO_AddrOf,
S.Context.getPointerType(To->getType()),
VK_RValue, OK_Ordinary, Loc);
@@ -8451,7 +8909,7 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
/// if a memcpy should be used instead.
static StmtResult
buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
- Expr *To, Expr *From,
+ const ExprBuilder &To, const ExprBuilder &From,
bool CopyingBaseSubobject, bool Copying,
unsigned Depth = 0) {
// C++11 [class.copy]p28:
@@ -8524,8 +8982,8 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
// Create the reference to operator=.
ExprResult OpEqualRef
- = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS,
- /*TemplateKWLoc=*/SourceLocation(),
+ = S.BuildMemberReferenceExpr(To.build(S, Loc), T, Loc, /*isArrow=*/false,
+ SS, /*TemplateKWLoc=*/SourceLocation(),
/*FirstQualifierInScope=*/0,
OpLookup,
/*TemplateArgs=*/0,
@@ -8535,9 +8993,10 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
// Build the call to the assignment operator.
+ Expr *FromInst = From.build(S, Loc);
ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0,
OpEqualRef.takeAs<Expr>(),
- Loc, &From, 1, Loc);
+ Loc, FromInst, Loc);
if (Call.isInvalid())
return StmtError();
@@ -8556,7 +9015,8 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
// operator is used.
const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T);
if (!ArrayTy) {
- ExprResult Assignment = S.CreateBuiltinBinOp(Loc, BO_Assign, To, From);
+ ExprResult Assignment = S.CreateBuiltinBinOp(
+ Loc, BO_Assign, To.build(S, Loc), From.build(S, Loc));
if (Assignment.isInvalid())
return StmtError();
return S.ActOnExprStmt(Assignment);
@@ -8589,31 +9049,28 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0);
IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc));
- // Create a reference to the iteration variable; we'll use this several
- // times throughout.
- Expr *IterationVarRef
- = S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc).take();
- assert(IterationVarRef && "Reference to invented variable cannot fail!");
- Expr *IterationVarRefRVal = S.DefaultLvalueConversion(IterationVarRef).take();
- assert(IterationVarRefRVal && "Conversion of invented variable cannot fail!");
+ // Creates a reference to the iteration variable.
+ RefBuilder IterationVarRef(IterationVar, SizeType);
+ LvalueConvBuilder IterationVarRefRVal(IterationVarRef);
// Create the DeclStmt that holds the iteration variable.
Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc);
// Subscript the "from" and "to" expressions with the iteration variable.
- From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc,
- IterationVarRefRVal,
- Loc));
- To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc,
- IterationVarRefRVal,
- Loc));
- if (!Copying) // Cast to rvalue
- From = CastForMoving(S, From);
+ SubscriptBuilder FromIndexCopy(From, IterationVarRefRVal);
+ MoveCastBuilder FromIndexMove(FromIndexCopy);
+ const ExprBuilder *FromIndex;
+ if (Copying)
+ FromIndex = &FromIndexCopy;
+ else
+ FromIndex = &FromIndexMove;
+
+ SubscriptBuilder ToIndex(To, IterationVarRefRVal);
// Build the copy/move for an individual element of the array.
StmtResult Copy =
buildSingleCopyAssignRecursively(S, Loc, ArrayTy->getElementType(),
- To, From, CopyingBaseSubobject,
+ ToIndex, *FromIndex, CopyingBaseSubobject,
Copying, Depth + 1);
// Bail out if copying fails or if we determined that we should use memcpy.
if (Copy.isInvalid() || !Copy.get())
@@ -8623,15 +9080,15 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
llvm::APInt Upper
= ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType));
Expr *Comparison
- = new (S.Context) BinaryOperator(IterationVarRefRVal,
+ = new (S.Context) BinaryOperator(IterationVarRefRVal.build(S, Loc),
IntegerLiteral::Create(S.Context, Upper, SizeType, Loc),
BO_NE, S.Context.BoolTy,
VK_RValue, OK_Ordinary, Loc, false);
// Create the pre-increment of the iteration variable.
Expr *Increment
- = new (S.Context) UnaryOperator(IterationVarRef, UO_PreInc, SizeType,
- VK_LValue, OK_Ordinary, Loc);
+ = new (S.Context) UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc,
+ SizeType, VK_LValue, OK_Ordinary, Loc);
// Construct the loop that copies all elements of this array.
return S.ActOnForStmt(Loc, Loc, InitStmt,
@@ -8642,7 +9099,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
static StmtResult
buildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
- Expr *To, Expr *From,
+ const ExprBuilder &To, const ExprBuilder &From,
bool CopyingBaseSubobject, bool Copying) {
// Maybe we should use a memcpy?
if (T->isArrayType() && !T.isConstQualified() && !T.isVolatileQualified() &&
@@ -8736,29 +9193,31 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
QualType ArgType = Context.getTypeDeclType(ClassDecl);
QualType RetType = Context.getLValueReferenceType(ArgType);
- if (ClassDecl->implicitCopyAssignmentHasConstParam())
+ bool Const = ClassDecl->implicitCopyAssignmentHasConstParam();
+ if (Const)
ArgType = ArgType.withConst();
ArgType = Context.getLValueReferenceType(ArgType);
+ bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
+ CXXCopyAssignment,
+ Const);
+
// An implicitly-declared copy assignment operator is an inline public
// member of its class.
DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationNameInfo NameInfo(Name, ClassLoc);
- CXXMethodDecl *CopyAssignment
- = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
- /*TInfo=*/0,
- /*StorageClass=*/SC_None,
- /*isInline=*/true, /*isConstexpr=*/false,
- SourceLocation());
+ CXXMethodDecl *CopyAssignment =
+ CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
+ /*TInfo=*/ 0, /*StorageClass=*/ SC_None,
+ /*isInline=*/ true, Constexpr, SourceLocation());
CopyAssignment->setAccess(AS_public);
CopyAssignment->setDefaulted();
CopyAssignment->setImplicit();
// Build an exception specification pointing back at this member.
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = CopyAssignment;
+ FunctionProtoType::ExtProtoInfo EPI =
+ getImplicitMethodEPI(*this, CopyAssignment);
CopyAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));
// Add the parameter to the operator.
@@ -8775,11 +9234,6 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment)
: ClassDecl->hasTrivialCopyAssignment());
- // C++0x [class.copy]p19:
- // .... If the class definition does not explicitly declare a copy
- // assignment operator, there is no user-declared move constructor, and
- // there is no user-declared move assignment operator, a copy assignment
- // operator is implicitly declared as defaulted.
if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment))
SetDeclDeleted(CopyAssignment, ClassLoc);
@@ -8793,6 +9247,58 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
return CopyAssignment;
}
+/// Diagnose an implicit copy operation for a class which is odr-used, but
+/// which is deprecated because the class has a user-declared copy constructor,
+/// copy assignment operator, or destructor.
+static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp,
+ SourceLocation UseLoc) {
+ assert(CopyOp->isImplicit());
+
+ CXXRecordDecl *RD = CopyOp->getParent();
+ CXXMethodDecl *UserDeclaredOperation = 0;
+
+ // In Microsoft mode, assignment operations don't affect constructors and
+ // vice versa.
+ if (RD->hasUserDeclaredDestructor()) {
+ UserDeclaredOperation = RD->getDestructor();
+ } else if (!isa<CXXConstructorDecl>(CopyOp) &&
+ RD->hasUserDeclaredCopyConstructor() &&
+ !S.getLangOpts().MicrosoftMode) {
+ // Find any user-declared copy constructor.
+ for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(),
+ E = RD->ctor_end(); I != E; ++I) {
+ if (I->isCopyConstructor()) {
+ UserDeclaredOperation = *I;
+ break;
+ }
+ }
+ assert(UserDeclaredOperation);
+ } else if (isa<CXXConstructorDecl>(CopyOp) &&
+ RD->hasUserDeclaredCopyAssignment() &&
+ !S.getLangOpts().MicrosoftMode) {
+ // Find any user-declared move assignment operator.
+ for (CXXRecordDecl::method_iterator I = RD->method_begin(),
+ E = RD->method_end(); I != E; ++I) {
+ if (I->isCopyAssignmentOperator()) {
+ UserDeclaredOperation = *I;
+ break;
+ }
+ }
+ assert(UserDeclaredOperation);
+ }
+
+ if (UserDeclaredOperation) {
+ S.Diag(UserDeclaredOperation->getLocation(),
+ diag::warn_deprecated_copy_operation)
+ << RD << /*copy assignment*/!isa<CXXConstructorDecl>(CopyOp)
+ << /*destructor*/isa<CXXDestructorDecl>(UserDeclaredOperation);
+ S.Diag(UseLoc, diag::note_member_synthesized_at)
+ << (isa<CXXConstructorDecl>(CopyOp) ? Sema::CXXCopyConstructor
+ : Sema::CXXCopyAssignment)
+ << RD;
+ }
+}
+
void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
CXXMethodDecl *CopyAssignOperator) {
assert((CopyAssignOperator->isDefaulted() &&
@@ -8808,8 +9314,15 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
CopyAssignOperator->setInvalidDecl();
return;
}
-
- CopyAssignOperator->setUsed();
+
+ // C++11 [class.copy]p18:
+ // The [definition of an implicitly declared copy assignment operator] is
+ // deprecated if the class has a user-declared copy constructor or a
+ // user-declared destructor.
+ if (getLangOpts().CPlusPlus11 && CopyAssignOperator->isImplicit())
+ diagnoseDeprecatedCopyOperation(*this, CopyAssignOperator, CurrentLocation);
+
+ CopyAssignOperator->markUsed(Context);
SynthesizedFunctionScope Scope(*this, CopyAssignOperator);
DiagnosticErrorTrap Trap(Diags);
@@ -8838,15 +9351,11 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
// Our location for everything implicitly-generated.
SourceLocation Loc = CopyAssignOperator->getLocation();
- // Construct a reference to the "other" object. We'll be using this
- // throughout the generated ASTs.
- Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_LValue, Loc).take();
- assert(OtherRef && "Reference to parameter cannot fail!");
-
- // Construct the "this" pointer. We'll be using this throughout the generated
- // ASTs.
- Expr *This = ActOnCXXThis(Loc).takeAs<Expr>();
- assert(This && "Reference to this cannot fail!");
+ // Builds a DeclRefExpr for the "other" object.
+ RefBuilder OtherRef(Other, OtherRefType);
+
+ // Builds the "this" pointer.
+ ThisBuilder This;
// Assign base classes.
bool Invalid = false;
@@ -8865,24 +9374,19 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
// Construct the "from" expression, which is an implicit cast to the
// appropriately-qualified base type.
- Expr *From = OtherRef;
- From = ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals),
- CK_UncheckedDerivedToBase,
- VK_LValue, &BasePath).take();
+ CastBuilder From(OtherRef, Context.getQualifiedType(BaseType, OtherQuals),
+ VK_LValue, BasePath);
// Dereference "this".
- ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
-
- // Implicitly cast "this" to the appropriately-qualified base type.
- To = ImpCastExprToType(To.take(),
- Context.getCVRQualifiedType(BaseType,
- CopyAssignOperator->getTypeQualifiers()),
- CK_UncheckedDerivedToBase,
- VK_LValue, &BasePath);
+ DerefBuilder DerefThis(This);
+ CastBuilder To(DerefThis,
+ Context.getCVRQualifiedType(
+ BaseType, CopyAssignOperator->getTypeQualifiers()),
+ VK_LValue, BasePath);
// Build the copy.
StmtResult Copy = buildSingleCopyAssign(*this, Loc, BaseType,
- To.get(), From,
+ To, From,
/*CopyingBaseSubobject=*/true,
/*Copying=*/true);
if (Copy.isInvalid()) {
@@ -8902,7 +9406,12 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
Field != FieldEnd; ++Field) {
if (Field->isUnnamedBitfield())
continue;
-
+
+ if (Field->isInvalidDecl()) {
+ Invalid = true;
+ continue;
+ }
+
// Check for members of reference type; we can't copy those.
if (Field->getType()->isReferenceType()) {
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
@@ -8943,20 +9452,14 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
LookupMemberName);
MemberLookup.addDecl(*Field);
MemberLookup.resolveKind();
- ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType,
- Loc, /*IsArrow=*/false,
- SS, SourceLocation(), 0,
- MemberLookup, 0);
- ExprResult To = BuildMemberReferenceExpr(This, This->getType(),
- Loc, /*IsArrow=*/true,
- SS, SourceLocation(), 0,
- MemberLookup, 0);
- assert(!From.isInvalid() && "Implicit field reference cannot fail");
- assert(!To.isInvalid() && "Implicit field reference cannot fail");
+
+ MemberBuilder From(OtherRef, OtherRefType, /*IsArrow=*/false, MemberLookup);
+
+ MemberBuilder To(This, getCurrentThisType(), /*IsArrow=*/true, MemberLookup);
// Build the copy of this field.
StmtResult Copy = buildSingleCopyAssign(*this, Loc, FieldType,
- To.get(), From.get(),
+ To, From,
/*CopyingBaseSubobject=*/false,
/*Copying=*/true);
if (Copy.isInvalid()) {
@@ -8972,7 +9475,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
if (!Invalid) {
// Add a "return *this;"
- ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
+ ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));
StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get());
if (Return.isInvalid())
@@ -9067,120 +9570,13 @@ Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXMethodDecl *MD) {
return ExceptSpec;
}
-/// Determine whether the class type has any direct or indirect virtual base
-/// classes which have a non-trivial move assignment operator.
-static bool
-hasVirtualBaseWithNonTrivialMoveAssignment(Sema &S, CXXRecordDecl *ClassDecl) {
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
- BaseEnd = ClassDecl->vbases_end();
- Base != BaseEnd; ++Base) {
- CXXRecordDecl *BaseClass =
- cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
-
- // Try to declare the move assignment. If it would be deleted, then the
- // class does not have a non-trivial move assignment.
- if (BaseClass->needsImplicitMoveAssignment())
- S.DeclareImplicitMoveAssignment(BaseClass);
-
- if (BaseClass->hasNonTrivialMoveAssignment())
- return true;
- }
-
- return false;
-}
-
-/// Determine whether the given type either has a move constructor or is
-/// trivially copyable.
-static bool
-hasMoveOrIsTriviallyCopyable(Sema &S, QualType Type, bool IsConstructor) {
- Type = S.Context.getBaseElementType(Type);
-
- // FIXME: Technically, non-trivially-copyable non-class types, such as
- // reference types, are supposed to return false here, but that appears
- // to be a standard defect.
- CXXRecordDecl *ClassDecl = Type->getAsCXXRecordDecl();
- if (!ClassDecl || !ClassDecl->getDefinition() || ClassDecl->isInvalidDecl())
- return true;
-
- if (Type.isTriviallyCopyableType(S.Context))
- return true;
-
- if (IsConstructor) {
- // FIXME: Need this because otherwise hasMoveConstructor isn't guaranteed to
- // give the right answer.
- if (ClassDecl->needsImplicitMoveConstructor())
- S.DeclareImplicitMoveConstructor(ClassDecl);
- return ClassDecl->hasMoveConstructor();
- }
-
- // FIXME: Need this because otherwise hasMoveAssignment isn't guaranteed to
- // give the right answer.
- if (ClassDecl->needsImplicitMoveAssignment())
- S.DeclareImplicitMoveAssignment(ClassDecl);
- return ClassDecl->hasMoveAssignment();
-}
-
-/// Determine whether all non-static data members and direct or virtual bases
-/// of class \p ClassDecl have either a move operation, or are trivially
-/// copyable.
-static bool subobjectsHaveMoveOrTrivialCopy(Sema &S, CXXRecordDecl *ClassDecl,
- bool IsConstructor) {
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- BaseEnd = ClassDecl->bases_end();
- Base != BaseEnd; ++Base) {
- if (Base->isVirtual())
- continue;
-
- if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(), IsConstructor))
- return false;
- }
-
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
- BaseEnd = ClassDecl->vbases_end();
- Base != BaseEnd; ++Base) {
- if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(), IsConstructor))
- return false;
- }
-
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd; ++Field) {
- if (!hasMoveOrIsTriviallyCopyable(S, Field->getType(), IsConstructor))
- return false;
- }
-
- return true;
-}
-
CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
- // C++11 [class.copy]p20:
- // If the definition of a class X does not explicitly declare a move
- // assignment operator, one will be implicitly declared as defaulted
- // if and only if:
- //
- // - [first 4 bullets]
assert(ClassDecl->needsImplicitMoveAssignment());
DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment);
if (DSM.isAlreadyBeingDeclared())
return 0;
- // [Checked after we build the declaration]
- // - the move assignment operator would not be implicitly defined as
- // deleted,
-
- // [DR1402]:
- // - X has no direct or indirect virtual base class with a non-trivial
- // move assignment operator, and
- // - each of X's non-static data members and direct or virtual base classes
- // has a type that either has a move assignment operator or is trivially
- // copyable.
- if (hasVirtualBaseWithNonTrivialMoveAssignment(*this, ClassDecl) ||
- !subobjectsHaveMoveOrTrivialCopy(*this, ClassDecl,/*Constructor*/false)) {
- ClassDecl->setFailedImplicitMoveAssignment();
- return 0;
- }
-
// Note: The following rules are largely analoguous to the move
// constructor rules.
@@ -9188,26 +9584,26 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
QualType RetType = Context.getLValueReferenceType(ArgType);
ArgType = Context.getRValueReferenceType(ArgType);
+ bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
+ CXXMoveAssignment,
+ false);
+
// An implicitly-declared move assignment operator is an inline public
// member of its class.
DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationNameInfo NameInfo(Name, ClassLoc);
- CXXMethodDecl *MoveAssignment
- = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
- /*TInfo=*/0,
- /*StorageClass=*/SC_None,
- /*isInline=*/true,
- /*isConstexpr=*/false,
- SourceLocation());
+ CXXMethodDecl *MoveAssignment =
+ CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
+ /*TInfo=*/0, /*StorageClass=*/SC_None,
+ /*isInline=*/true, Constexpr, SourceLocation());
MoveAssignment->setAccess(AS_public);
MoveAssignment->setDefaulted();
MoveAssignment->setImplicit();
// Build an exception specification pointing back at this member.
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = MoveAssignment;
+ FunctionProtoType::ExtProtoInfo EPI =
+ getImplicitMethodEPI(*this, MoveAssignment);
MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));
// Add the parameter to the operator.
@@ -9224,18 +9620,9 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment)
: ClassDecl->hasTrivialMoveAssignment());
- // C++0x [class.copy]p9:
- // If the definition of a class X does not explicitly declare a move
- // assignment operator, one will be implicitly declared as defaulted if and
- // only if:
- // [...]
- // - the move assignment operator would not be implicitly defined as
- // deleted.
if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) {
- // Cache this result so that we don't try to generate this over and over
- // on every lookup, leaking memory and wasting time.
- ClassDecl->setFailedImplicitMoveAssignment();
- return 0;
+ ClassDecl->setImplicitMoveAssignmentIsDeleted();
+ SetDeclDeleted(MoveAssignment, ClassLoc);
}
// Note that we have added this copy-assignment operator.
@@ -9248,6 +9635,94 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
return MoveAssignment;
}
+/// Check if we're implicitly defining a move assignment operator for a class
+/// with virtual bases. Such a move assignment might move-assign the virtual
+/// base multiple times.
+static void checkMoveAssignmentForRepeatedMove(Sema &S, CXXRecordDecl *Class,
+ SourceLocation CurrentLocation) {
+ assert(!Class->isDependentContext() && "should not define dependent move");
+
+ // Only a virtual base could get implicitly move-assigned multiple times.
+ // Only a non-trivial move assignment can observe this. We only want to
+ // diagnose if we implicitly define an assignment operator that assigns
+ // two base classes, both of which move-assign the same virtual base.
+ if (Class->getNumVBases() == 0 || Class->hasTrivialMoveAssignment() ||
+ Class->getNumBases() < 2)
+ return;
+
+ llvm::SmallVector<CXXBaseSpecifier *, 16> Worklist;
+ typedef llvm::DenseMap<CXXRecordDecl*, CXXBaseSpecifier*> VBaseMap;
+ VBaseMap VBases;
+
+ for (CXXRecordDecl::base_class_iterator BI = Class->bases_begin(),
+ BE = Class->bases_end();
+ BI != BE; ++BI) {
+ Worklist.push_back(&*BI);
+ while (!Worklist.empty()) {
+ CXXBaseSpecifier *BaseSpec = Worklist.pop_back_val();
+ CXXRecordDecl *Base = BaseSpec->getType()->getAsCXXRecordDecl();
+
+ // If the base has no non-trivial move assignment operators,
+ // we don't care about moves from it.
+ if (!Base->hasNonTrivialMoveAssignment())
+ continue;
+
+ // If there's nothing virtual here, skip it.
+ if (!BaseSpec->isVirtual() && !Base->getNumVBases())
+ continue;
+
+ // If we're not actually going to call a move assignment for this base,
+ // or the selected move assignment is trivial, skip it.
+ Sema::SpecialMemberOverloadResult *SMOR =
+ S.LookupSpecialMember(Base, Sema::CXXMoveAssignment,
+ /*ConstArg*/false, /*VolatileArg*/false,
+ /*RValueThis*/true, /*ConstThis*/false,
+ /*VolatileThis*/false);
+ if (!SMOR->getMethod() || SMOR->getMethod()->isTrivial() ||
+ !SMOR->getMethod()->isMoveAssignmentOperator())
+ continue;
+
+ if (BaseSpec->isVirtual()) {
+ // We're going to move-assign this virtual base, and its move
+ // assignment operator is not trivial. If this can happen for
+ // multiple distinct direct bases of Class, diagnose it. (If it
+ // only happens in one base, we'll diagnose it when synthesizing
+ // that base class's move assignment operator.)
+ CXXBaseSpecifier *&Existing =
+ VBases.insert(std::make_pair(Base->getCanonicalDecl(), BI))
+ .first->second;
+ if (Existing && Existing != BI) {
+ S.Diag(CurrentLocation, diag::warn_vbase_moved_multiple_times)
+ << Class << Base;
+ S.Diag(Existing->getLocStart(), diag::note_vbase_moved_here)
+ << (Base->getCanonicalDecl() ==
+ Existing->getType()->getAsCXXRecordDecl()->getCanonicalDecl())
+ << Base << Existing->getType() << Existing->getSourceRange();
+ S.Diag(BI->getLocStart(), diag::note_vbase_moved_here)
+ << (Base->getCanonicalDecl() ==
+ BI->getType()->getAsCXXRecordDecl()->getCanonicalDecl())
+ << Base << BI->getType() << BaseSpec->getSourceRange();
+
+ // Only diagnose each vbase once.
+ Existing = 0;
+ }
+ } else {
+ // Only walk over bases that have defaulted move assignment operators.
+ // We assume that any user-provided move assignment operator handles
+ // the multiple-moves-of-vbase case itself somehow.
+ if (!SMOR->getMethod()->isDefaulted())
+ continue;
+
+ // We're going to move the base classes of Base. Add them to the list.
+ for (CXXRecordDecl::base_class_iterator BI = Base->bases_begin(),
+ BE = Base->bases_end();
+ BI != BE; ++BI)
+ Worklist.push_back(&*BI);
+ }
+ }
+ }
+}
+
void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
CXXMethodDecl *MoveAssignOperator) {
assert((MoveAssignOperator->isDefaulted() &&
@@ -9264,7 +9739,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
return;
}
- MoveAssignOperator->setUsed();
+ MoveAssignOperator->markUsed(Context);
SynthesizedFunctionScope Scope(*this, MoveAssignOperator);
DiagnosticErrorTrap Trap(Diags);
@@ -9277,6 +9752,10 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
// are assigned, in the order in which they were declared in the class
// definition.
+ // Issue a warning if our implicit move assignment operator will move
+ // from a virtual base more than once.
+ checkMoveAssignmentForRepeatedMove(*this, ClassDecl, CurrentLocation);
+
// The statements that form the synthesized function body.
SmallVector<Stmt*, 8> Statements;
@@ -9284,28 +9763,32 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
ParmVarDecl *Other = MoveAssignOperator->getParamDecl(0);
QualType OtherRefType = Other->getType()->
getAs<RValueReferenceType>()->getPointeeType();
- assert(OtherRefType.getQualifiers() == 0 &&
+ assert(!OtherRefType.getQualifiers() &&
"Bad argument type of defaulted move assignment");
// Our location for everything implicitly-generated.
SourceLocation Loc = MoveAssignOperator->getLocation();
- // Construct a reference to the "other" object. We'll be using this
- // throughout the generated ASTs.
- Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_LValue, Loc).take();
- assert(OtherRef && "Reference to parameter cannot fail!");
+ // Builds a reference to the "other" object.
+ RefBuilder OtherRef(Other, OtherRefType);
// Cast to rvalue.
- OtherRef = CastForMoving(*this, OtherRef);
+ MoveCastBuilder MoveOther(OtherRef);
- // Construct the "this" pointer. We'll be using this throughout the generated
- // ASTs.
- Expr *This = ActOnCXXThis(Loc).takeAs<Expr>();
- assert(This && "Reference to this cannot fail!");
+ // Builds the "this" pointer.
+ ThisBuilder This;
// Assign base classes.
bool Invalid = false;
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
E = ClassDecl->bases_end(); Base != E; ++Base) {
+ // C++11 [class.copy]p28:
+ // It is unspecified whether subobjects representing virtual base classes
+ // are assigned more than once by the implicitly-defined copy assignment
+ // operator.
+ // FIXME: Do not assign to a vbase that will be assigned by some other base
+ // class. For a move-assignment, this can result in the vbase being moved
+ // multiple times.
+
// Form the assignment:
// static_cast<Base*>(this)->Base::operator=(static_cast<Base&&>(other));
QualType BaseType = Base->getType().getUnqualifiedType();
@@ -9319,23 +9802,20 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
// Construct the "from" expression, which is an implicit cast to the
// appropriately-qualified base type.
- Expr *From = OtherRef;
- From = ImpCastExprToType(From, BaseType, CK_UncheckedDerivedToBase,
- VK_XValue, &BasePath).take();
+ CastBuilder From(OtherRef, BaseType, VK_XValue, BasePath);
// Dereference "this".
- ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
+ DerefBuilder DerefThis(This);
// Implicitly cast "this" to the appropriately-qualified base type.
- To = ImpCastExprToType(To.take(),
- Context.getCVRQualifiedType(BaseType,
- MoveAssignOperator->getTypeQualifiers()),
- CK_UncheckedDerivedToBase,
- VK_LValue, &BasePath);
+ CastBuilder To(DerefThis,
+ Context.getCVRQualifiedType(
+ BaseType, MoveAssignOperator->getTypeQualifiers()),
+ VK_LValue, BasePath);
// Build the move.
StmtResult Move = buildSingleCopyAssign(*this, Loc, BaseType,
- To.get(), From,
+ To, From,
/*CopyingBaseSubobject=*/true,
/*Copying=*/false);
if (Move.isInvalid()) {
@@ -9356,6 +9836,11 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
if (Field->isUnnamedBitfield())
continue;
+ if (Field->isInvalidDecl()) {
+ Invalid = true;
+ continue;
+ }
+
// Check for members of reference type; we can't move those.
if (Field->getType()->isReferenceType()) {
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
@@ -9391,29 +9876,22 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
}
// Build references to the field in the object we're copying from and to.
- CXXScopeSpec SS; // Intentionally empty
LookupResult MemberLookup(*this, Field->getDeclName(), Loc,
LookupMemberName);
MemberLookup.addDecl(*Field);
MemberLookup.resolveKind();
- ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType,
- Loc, /*IsArrow=*/false,
- SS, SourceLocation(), 0,
- MemberLookup, 0);
- ExprResult To = BuildMemberReferenceExpr(This, This->getType(),
- Loc, /*IsArrow=*/true,
- SS, SourceLocation(), 0,
- MemberLookup, 0);
- assert(!From.isInvalid() && "Implicit field reference cannot fail");
- assert(!To.isInvalid() && "Implicit field reference cannot fail");
-
- assert(!From.get()->isLValue() && // could be xvalue or prvalue
+ MemberBuilder From(MoveOther, OtherRefType,
+ /*IsArrow=*/false, MemberLookup);
+ MemberBuilder To(This, getCurrentThisType(),
+ /*IsArrow=*/true, MemberLookup);
+
+ assert(!From.build(*this, Loc)->isLValue() && // could be xvalue or prvalue
"Member reference with rvalue base must be rvalue except for reference "
"members, which aren't allowed for move assignment.");
// Build the move of this field.
StmtResult Move = buildSingleCopyAssign(*this, Loc, FieldType,
- To.get(), From.get(),
+ To, From,
/*CopyingBaseSubobject=*/false,
/*Copying=*/false);
if (Move.isInvalid()) {
@@ -9429,7 +9907,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
if (!Invalid) {
// Add a "return *this;"
- ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
+ ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));
StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get());
if (Return.isInvalid())
@@ -9557,9 +10035,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
CopyConstructor->setDefaulted();
// Build an exception specification pointing back at this member.
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = CopyConstructor;
+ FunctionProtoType::ExtProtoInfo EPI =
+ getImplicitMethodEPI(*this, CopyConstructor);
CopyConstructor->setType(
Context.getFunctionType(Context.VoidTy, ArgType, EPI));
@@ -9576,11 +10053,6 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
: ClassDecl->hasTrivialCopyConstructor());
- // C++11 [class.copy]p8:
- // ... If the class definition does not explicitly declare a copy
- // constructor, there is no user-declared move constructor, and there is no
- // user-declared move assignment operator, a copy constructor is implicitly
- // declared as defaulted.
if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor))
SetDeclDeleted(CopyConstructor, ClassLoc);
@@ -9605,6 +10077,13 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CXXRecordDecl *ClassDecl = CopyConstructor->getParent();
assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
+ // C++11 [class.copy]p7:
+ // The [definition of an implicitly declared copy constructor] is
+ // deprecated if the class has a user-declared copy assignment operator
+ // or a user-declared destructor.
+ if (getLangOpts().CPlusPlus11 && CopyConstructor->isImplicit())
+ diagnoseDeprecatedCopyOperation(*this, CopyConstructor, CurrentLocation);
+
SynthesizedFunctionScope Scope(*this, CopyConstructor);
DiagnosticErrorTrap Trap(Diags);
@@ -9615,15 +10094,12 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CopyConstructor->setInvalidDecl();
} else {
Sema::CompoundScopeRAII CompoundScope(*this);
- CopyConstructor->setBody(ActOnCompoundStmt(CopyConstructor->getLocation(),
- CopyConstructor->getLocation(),
- MultiStmtArg(),
- /*isStmtExpr=*/false)
- .takeAs<Stmt>());
- CopyConstructor->setImplicitlyDefined(true);
+ CopyConstructor->setBody(ActOnCompoundStmt(
+ CopyConstructor->getLocation(), CopyConstructor->getLocation(), None,
+ /*isStmtExpr=*/ false).takeAs<Stmt>());
}
-
- CopyConstructor->setUsed();
+
+ CopyConstructor->markUsed(Context);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(CopyConstructor);
}
@@ -9696,29 +10172,12 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXMethodDecl *MD) {
CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
CXXRecordDecl *ClassDecl) {
- // C++11 [class.copy]p9:
- // If the definition of a class X does not explicitly declare a move
- // constructor, one will be implicitly declared as defaulted if and only if:
- //
- // - [first 4 bullets]
assert(ClassDecl->needsImplicitMoveConstructor());
DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor);
if (DSM.isAlreadyBeingDeclared())
return 0;
- // [Checked after we build the declaration]
- // - the move assignment operator would not be implicitly defined as
- // deleted,
-
- // [DR1402]:
- // - each of X's non-static data members and direct or virtual base classes
- // has a type that either has a move constructor or is trivially copyable.
- if (!subobjectsHaveMoveOrTrivialCopy(*this, ClassDecl, /*Constructor*/true)) {
- ClassDecl->setFailedImplicitMoveConstructor();
- return 0;
- }
-
QualType ClassType = Context.getTypeDeclType(ClassDecl);
QualType ArgType = Context.getRValueReferenceType(ClassType);
@@ -9732,7 +10191,7 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationNameInfo NameInfo(Name, ClassLoc);
- // C++0x [class.copy]p11:
+ // C++11 [class.copy]p11:
// An implicitly-declared copy/move constructor is an inline public
// member of its class.
CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create(
@@ -9743,9 +10202,8 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
MoveConstructor->setDefaulted();
// Build an exception specification pointing back at this member.
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = MoveConstructor;
+ FunctionProtoType::ExtProtoInfo EPI =
+ getImplicitMethodEPI(*this, MoveConstructor);
MoveConstructor->setType(
Context.getFunctionType(Context.VoidTy, ArgType, EPI));
@@ -9762,16 +10220,9 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
: ClassDecl->hasTrivialMoveConstructor());
- // C++0x [class.copy]p9:
- // If the definition of a class X does not explicitly declare a move
- // constructor, one will be implicitly declared as defaulted if and only if:
- // [...]
- // - the move constructor would not be implicitly defined as deleted.
if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) {
- // Cache this result so that we don't try to generate this over and over
- // on every lookup, leaking memory and wasting time.
- ClassDecl->setFailedImplicitMoveConstructor();
- return 0;
+ ClassDecl->setImplicitMoveConstructorIsDeleted();
+ SetDeclDeleted(MoveConstructor, ClassLoc);
}
// Note that we have declared this constructor.
@@ -9805,15 +10256,12 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
MoveConstructor->setInvalidDecl();
} else {
Sema::CompoundScopeRAII CompoundScope(*this);
- MoveConstructor->setBody(ActOnCompoundStmt(MoveConstructor->getLocation(),
- MoveConstructor->getLocation(),
- MultiStmtArg(),
- /*isStmtExpr=*/false)
- .takeAs<Stmt>());
- MoveConstructor->setImplicitlyDefined(true);
+ MoveConstructor->setBody(ActOnCompoundStmt(
+ MoveConstructor->getLocation(), MoveConstructor->getLocation(), None,
+ /*isStmtExpr=*/ false).takeAs<Stmt>());
}
- MoveConstructor->setUsed();
+ MoveConstructor->markUsed(Context);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(MoveConstructor);
@@ -9821,64 +10269,96 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
}
bool Sema::isImplicitlyDeleted(FunctionDecl *FD) {
- return FD->isDeleted() &&
- (FD->isDefaulted() || FD->isImplicit()) &&
- isa<CXXMethodDecl>(FD);
-}
-
-/// \brief Mark the call operator of the given lambda closure type as "used".
-static void markLambdaCallOperatorUsed(Sema &S, CXXRecordDecl *Lambda) {
- CXXMethodDecl *CallOperator
- = cast<CXXMethodDecl>(
- Lambda->lookup(
- S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).front());
- CallOperator->setReferenced();
- CallOperator->setUsed();
+ return FD->isDeleted() && FD->isDefaulted() && isa<CXXMethodDecl>(FD);
}
void Sema::DefineImplicitLambdaToFunctionPointerConversion(
- SourceLocation CurrentLocation,
- CXXConversionDecl *Conv)
-{
+ SourceLocation CurrentLocation,
+ CXXConversionDecl *Conv) {
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 = 0;
+
- // Make sure that the lambda call operator is marked used.
- markLambdaCallOperatorUsed(*this, Lambda);
-
- Conv->setUsed();
-
+ // Retrieve the corresponding call-operator specialization.
+ if (Lambda->isGenericLambda()) {
+ assert(Conv->isFunctionTemplateSpecialization());
+ FunctionTemplateDecl *CallOpTemplate =
+ CallOp->getDescribedFunctionTemplate();
+ DeducedTemplateArgs = Conv->getTemplateSpecializationArgs();
+ void *InsertPos = 0;
+ FunctionDecl *CallOpSpec = CallOpTemplate->findSpecialization(
+ DeducedTemplateArgs->data(),
+ DeducedTemplateArgs->size(),
+ InsertPos);
+ assert(CallOpSpec &&
+ "Conversion operator must have a corresponding call operator");
+ CallOp = cast<CXXMethodDecl>(CallOpSpec);
+ }
+ // Mark the call operator referenced (and add to pending instantiations
+ // if necessary).
+ // For both the conversion and static-invoker template specializations
+ // we construct their body's in this function, so no need to add them
+ // to the PendingInstantiations.
+ MarkFunctionReferenced(CurrentLocation, CallOp);
+
SynthesizedFunctionScope Scope(*this, Conv);
DiagnosticErrorTrap Trap(Diags);
+
+ // Retreive 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 = 0;
+ FunctionDecl *InvokeSpec = InvokeTemplate->findSpecialization(
+ DeducedTemplateArgs->data(),
+ DeducedTemplateArgs->size(),
+ InsertPos);
+ assert(InvokeSpec &&
+ "Must have a corresponding static invoker specialization");
+ Invoker = cast<CXXMethodDecl>(InvokeSpec);
+ }
+ // Construct the body of the conversion function { return __invoke; }.
+ Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->getType(),
+ VK_LValue, Conv->getLocation()).take();
+ assert(FunctionRef && "Can't refer to __invoke function?");
+ Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take();
+ Conv->setBody(new (Context) CompoundStmt(Context, Return,
+ Conv->getLocation(),
+ Conv->getLocation()));
+
+ Conv->markUsed(Context);
+ Conv->setReferenced();
- // Return the address of the __invoke function.
- DeclarationName InvokeName = &Context.Idents.get("__invoke");
- CXXMethodDecl *Invoke
- = cast<CXXMethodDecl>(Lambda->lookup(InvokeName).front());
- Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(),
- VK_LValue, Conv->getLocation()).take();
- assert(FunctionRef && "Can't refer to __invoke function?");
- Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take();
- Conv->setBody(new (Context) CompoundStmt(Context, Return,
- Conv->getLocation(),
- Conv->getLocation()));
-
// Fill in the __invoke function with a dummy implementation. IR generation
// will fill in the actual details.
- Invoke->setUsed();
- Invoke->setReferenced();
- Invoke->setBody(new (Context) CompoundStmt(Conv->getLocation()));
-
+ Invoker->markUsed(Context);
+ Invoker->setReferenced();
+ Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));
+
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Conv);
- L->CompletedImplicitDefinition(Invoke);
- }
+ L->CompletedImplicitDefinition(Invoker);
+ }
}
+
+
void Sema::DefineImplicitLambdaToBlockPointerConversion(
SourceLocation CurrentLocation,
CXXConversionDecl *Conv)
{
- Conv->setUsed();
+ assert(!Conv->getParent()->isGenericLambda());
+
+ Conv->markUsed(Context);
SynthesizedFunctionScope Scope(*this, Conv);
DiagnosticErrorTrap Trap(Diags);
@@ -10057,12 +10537,14 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
SmallVector<Expr *, 8> AllArgs;
bool Invalid = GatherArgumentsForCall(Loc, Constructor,
- Proto, 0, Args, NumArgs, AllArgs,
+ Proto, 0,
+ llvm::makeArrayRef(Args, NumArgs),
+ AllArgs,
CallType, AllowExplicit,
IsListInitialization);
ConvertedArgs.append(AllArgs.begin(), AllArgs.end());
- DiagnoseSentinelCalls(Constructor, Loc, AllArgs.data(), AllArgs.size());
+ DiagnoseSentinelCalls(Constructor, Loc, AllArgs);
CheckConstructorCall(Constructor,
llvm::makeArrayRef<const Expr *>(AllArgs.data(),
@@ -10356,11 +10838,12 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
if (!TpDecl)
TpDecl = FnDecl->getPrimaryTemplate();
- // template <char...> type operator "" name() is the only valid template
- // signature, and the only valid signature with no parameters.
+ // template <char...> type operator "" name() and
+ // template <class T, T...> type operator "" name() are the only valid
+ // template signatures, and the only valid signatures with no parameters.
if (TpDecl) {
if (FnDecl->param_size() == 0) {
- // Must have only one template parameter
+ // Must have one or two template parameters
TemplateParameterList *Params = TpDecl->getTemplateParameters();
if (Params->size() == 1) {
NonTypeTemplateParmDecl *PmDecl =
@@ -10370,6 +10853,27 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
if (PmDecl && PmDecl->isTemplateParameterPack() &&
Context.hasSameType(PmDecl->getType(), Context.CharTy))
Valid = true;
+ } else if (Params->size() == 2) {
+ TemplateTypeParmDecl *PmType =
+ dyn_cast<TemplateTypeParmDecl>(Params->getParam(0));
+ NonTypeTemplateParmDecl *PmArgs =
+ dyn_cast<NonTypeTemplateParmDecl>(Params->getParam(1));
+
+ // The second template parameter must be a parameter pack with the
+ // first template parameter as its type.
+ if (PmType && PmArgs &&
+ !PmType->isTemplateParameterPack() &&
+ PmArgs->isTemplateParameterPack()) {
+ const TemplateTypeParmType *TArgs =
+ PmArgs->getType()->getAs<TemplateTypeParmType>();
+ if (TArgs && TArgs->getDepth() == PmType->getDepth() &&
+ TArgs->getIndex() == PmType->getIndex()) {
+ Valid = true;
+ if (ActiveTemplateInstantiations.empty())
+ Diag(FnDecl->getLocation(),
+ diag::ext_string_literal_operator_template);
+ }
+ }
}
}
} else if (FnDecl->param_size()) {
@@ -10383,7 +10887,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
if (Context.hasSameType(T, Context.UnsignedLongLongTy) ||
Context.hasSameType(T, Context.LongDoubleTy) ||
Context.hasSameType(T, Context.CharTy) ||
- Context.hasSameType(T, Context.WCharTy) ||
+ Context.hasSameType(T, Context.WideCharTy) ||
Context.hasSameType(T, Context.Char16Ty) ||
Context.hasSameType(T, Context.Char32Ty)) {
if (++Param == FnDecl->param_end())
@@ -10413,7 +10917,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
// const char *, const wchar_t*, const char16_t*, and const char32_t*
// are allowed as the first parameter to a two-parameter function
if (!(Context.hasSameType(T, Context.CharTy) ||
- Context.hasSameType(T, Context.WCharTy) ||
+ Context.hasSameType(T, Context.WideCharTy) ||
Context.hasSameType(T, Context.Char16Ty) ||
Context.hasSameType(T, Context.Char32Ty)))
goto FinishedParams;
@@ -10452,7 +10956,8 @@ FinishedParams:
// C++11 [usrlit.suffix]p1:
// Literal suffix identifiers that do not start with an underscore
// are reserved for future standardization.
- Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved);
+ Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved)
+ << NumericLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
}
return false;
@@ -10599,13 +11104,13 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
EnterExpressionEvaluationContext scope(*this, PotentiallyEvaluated);
// C++ [except.handle]p16:
- // The object declared in an exception-declaration or, if the
- // exception-declaration does not specify a name, a temporary (12.2) is
+ // The object declared in an exception-declaration or, if the
+ // exception-declaration does not specify a name, a temporary (12.2) is
// copy-initialized (8.5) from the exception object. [...]
// The object is destroyed when the handler exits, after the destruction
// of any automatic objects initialized within the handler.
//
- // We just pretend to initialize the object with itself, then make sure
+ // We just pretend to initialize the object with itself, then make sure
// it can be destroyed later.
QualType initType = ExDeclType;
@@ -10623,7 +11128,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
else {
// If the constructor used was non-trivial, set this as the
// "initializer".
- CXXConstructExpr *construct = cast<CXXConstructExpr>(result.take());
+ CXXConstructExpr *construct = result.takeAs<CXXConstructExpr>();
if (!construct->getConstructor()->isTrivial()) {
Expr *init = MaybeCreateExprWithCleanups(construct);
ExDecl->setInit(init);
@@ -10826,13 +11331,10 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
bool isExplicitSpecialization = false;
bool Invalid = false;
- if (TemplateParameterList *TemplateParams
- = MatchTemplateParametersToScopeSpecifier(TagLoc, NameLoc, SS,
- TempParamLists.data(),
- TempParamLists.size(),
- /*friend*/ true,
- isExplicitSpecialization,
- Invalid)) {
+ if (TemplateParameterList *TemplateParams =
+ MatchTemplateParametersToScopeSpecifier(
+ TagLoc, NameLoc, SS, TempParamLists, /*friend*/ true,
+ isExplicitSpecialization, Invalid)) {
if (TemplateParams->size() > 0) {
// This is a declaration of a class template.
if (Invalid)
@@ -10916,6 +11418,8 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
// Handle the case of a templated-scope friend class. e.g.
// template <class T> class A<T>::B;
// FIXME: we don't support these right now.
+ Diag(NameLoc, diag::warn_template_qualified_friend_unsupported)
+ << SS.getScopeRep() << SS.getRange() << cast<CXXRecordDecl>(CurContext);
ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name);
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
@@ -11080,28 +11584,61 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
ForRedeclaration);
- // FIXME: there are different rules in local classes
+ // There are five cases here.
+ // - There's no scope specifier and we're in a local class. Only look
+ // for functions declared in the immediately-enclosing block scope.
+ // We recover from invalid scope qualifiers as if they just weren't there.
+ FunctionDecl *FunctionContainingLocalClass = 0;
+ if ((SS.isInvalid() || !SS.isSet()) &&
+ (FunctionContainingLocalClass =
+ cast<CXXRecordDecl>(CurContext)->isLocalClass())) {
+ // C++11 [class.friend]p11:
+ // If a friend declaration appears in a local class and the name
+ // specified is an unqualified name, a prior declaration is
+ // looked up without considering scopes that are outside the
+ // innermost enclosing non-class scope. For a friend function
+ // declaration, if there is no prior declaration, the program is
+ // ill-formed.
+
+ // Find the innermost enclosing non-class scope. This is the block
+ // scope containing the local class definition (or for a nested class,
+ // the outer local class).
+ DCScope = S->getFnParent();
+
+ // Look up the function name in the scope.
+ Previous.clear(LookupLocalFriendName);
+ LookupName(Previous, S, /*AllowBuiltinCreation*/false);
+
+ if (!Previous.empty()) {
+ // All possible previous declarations must have the same context:
+ // either they were declared at block scope or they are members of
+ // one of the enclosing local classes.
+ DC = Previous.getRepresentativeDecl()->getDeclContext();
+ } else {
+ // This is ill-formed, but provide the context that we would have
+ // declared the function in, if we were permitted to, for error recovery.
+ DC = FunctionContainingLocalClass;
+ }
+ adjustContextForLocalExternDecl(DC);
+
+ // C++ [class.friend]p6:
+ // A function can be defined in a friend declaration of a class if and
+ // only if the class is a non-local class (9.8), the function name is
+ // unqualified, and the function has namespace scope.
+ if (D.isFunctionDefinition()) {
+ Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class);
+ }
- // There are four cases here.
// - There's no scope specifier, in which case we just go to the
// appropriate scope and look for a function or function template
// there as appropriate.
- // Recover from invalid scope qualifiers as if they just weren't there.
- if (SS.isInvalid() || !SS.isSet()) {
- // C++0x [namespace.memdef]p3:
+ } else if (SS.isInvalid() || !SS.isSet()) {
+ // C++11 [namespace.memdef]p3:
// If the name in a friend declaration is neither qualified nor
// a template-id and the declaration is a function or an
// elaborated-type-specifier, the lookup to determine whether
// the entity has been previously declared shall not consider
// any scopes outside the innermost enclosing namespace.
- // C++0x [class.friend]p11:
- // If a friend declaration appears in a local class and the name
- // specified is an unqualified name, a prior declaration is
- // looked up without considering scopes that are outside the
- // innermost enclosing non-class scope. For a friend function
- // declaration, if there is no prior declaration, the program is
- // ill-formed.
- bool isLocal = cast<CXXRecordDecl>(CurContext)->isLocalClass();
bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId;
// Find the appropriate context according to the above.
@@ -11124,10 +11661,6 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
while (true) {
LookupQualifiedName(Previous, LookupDC);
- // TODO: decide what we think about using declarations.
- if (isLocal)
- break;
-
if (!Previous.empty()) {
DC = LookupDC;
break;
@@ -11142,15 +11675,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
}
DCScope = getScopeForDeclContext(S, DC);
-
- // C++ [class.friend]p6:
- // A function can be defined in a friend declaration of a class if and
- // only if the class is a non-local class (9.8), the function name is
- // unqualified, and the function has namespace scope.
- if (isLocal && D.isFunctionDefinition()) {
- Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class);
- }
-
+
// - There's a non-dependent scope specifier, in which case we
// compute it and do a previous lookup there for a function
// or function template.
@@ -11242,15 +11767,18 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
FakeDCScope.setEntity(DC);
DCScope = &FakeDCScope;
}
-
+
bool AddToScope = true;
NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous,
TemplateParams, AddToScope);
if (!ND) return 0;
- assert(ND->getDeclContext() == DC);
assert(ND->getLexicalDeclContext() == CurContext);
+ // If we performed typo correction, we might have added a scope specifier
+ // and changed the decl context.
+ DC = ND->getDeclContext();
+
// Add the function declaration to the appropriate lookup tables,
// adjusting the redeclarations list as necessary. We don't
// want to do this yet if the friending class is dependent.
@@ -11281,6 +11809,18 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
else
FD = cast<FunctionDecl>(ND);
+ // C++11 [dcl.fct.default]p4: If a friend declaration specifies a
+ // default argument expression, that declaration shall be a definition
+ // and shall be the only declaration of the function or function
+ // template in the translation unit.
+ if (functionDeclHasDefaultArgument(FD)) {
+ if (FunctionDecl *OldFD = FD->getPreviousDecl()) {
+ Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_redeclared);
+ Diag(OldFD->getLocation(), diag::note_previous_declaration);
+ } else if (!D.isFunctionDefinition())
+ Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_must_be_def);
+ }
+
// Mark templated-scope function declarations as unsupported.
if (FD->getNumTemplateParameterLists())
FrD->setUnsupportedFriend(true);
@@ -11346,7 +11886,8 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
CXXSpecialMember Member = getSpecialMember(MD);
if (Member == CXXInvalid) {
- Diag(DefaultLoc, diag::err_default_special_members);
+ if (!MD->isInvalidDecl())
+ Diag(DefaultLoc, diag::err_default_special_members);
return;
}
@@ -11374,47 +11915,29 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
ResolveExceptionSpec(DefaultLoc,
MD->getType()->castAs<FunctionProtoType>());
+ if (MD->isInvalidDecl())
+ return;
+
switch (Member) {
- case CXXDefaultConstructor: {
- CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD);
- if (!CD->isInvalidDecl())
- DefineImplicitDefaultConstructor(DefaultLoc, CD);
+ case CXXDefaultConstructor:
+ DefineImplicitDefaultConstructor(DefaultLoc,
+ cast<CXXConstructorDecl>(MD));
break;
- }
-
- case CXXCopyConstructor: {
- CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD);
- if (!CD->isInvalidDecl())
- DefineImplicitCopyConstructor(DefaultLoc, CD);
+ case CXXCopyConstructor:
+ DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD));
break;
- }
-
- case CXXCopyAssignment: {
- if (!MD->isInvalidDecl())
- DefineImplicitCopyAssignment(DefaultLoc, MD);
+ case CXXCopyAssignment:
+ DefineImplicitCopyAssignment(DefaultLoc, MD);
break;
- }
-
- case CXXDestructor: {
- CXXDestructorDecl *DD = cast<CXXDestructorDecl>(MD);
- if (!DD->isInvalidDecl())
- DefineImplicitDestructor(DefaultLoc, DD);
+ case CXXDestructor:
+ DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(MD));
break;
- }
-
- case CXXMoveConstructor: {
- CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD);
- if (!CD->isInvalidDecl())
- DefineImplicitMoveConstructor(DefaultLoc, CD);
+ case CXXMoveConstructor:
+ DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD));
break;
- }
-
- case CXXMoveAssignment: {
- if (!MD->isInvalidDecl())
- DefineImplicitMoveAssignment(DefaultLoc, MD);
+ case CXXMoveAssignment:
+ DefineImplicitMoveAssignment(DefaultLoc, MD);
break;
- }
-
case CXXInvalid:
llvm_unreachable("Invalid special member.");
}
@@ -11454,27 +11977,11 @@ bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
if (NewCC == OldCC)
return false;
- // If either of the calling conventions are set to "default", we need to pick
- // something more sensible based on the target. This supports code where the
- // one method explicitly sets thiscall, and another has no explicit calling
- // convention.
- CallingConv Default =
- Context.getTargetInfo().getDefaultCallingConv(TargetInfo::CCMT_Member);
- if (NewCC == CC_Default)
- NewCC = Default;
- if (OldCC == CC_Default)
- OldCC = Default;
-
- // If the calling conventions still don't match, then report the error
- if (NewCC != OldCC) {
- Diag(New->getLocation(),
- diag::err_conflicting_overriding_cc_attributes)
- << New->getDeclName() << New->getType() << Old->getType();
- Diag(Old->getLocation(), diag::note_overridden_virtual_function);
- return true;
- }
-
- return false;
+ Diag(New->getLocation(),
+ diag::err_conflicting_overriding_cc_attributes)
+ << New->getDeclName() << New->getType() << Old->getType();
+ Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+ return true;
}
bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
@@ -11595,13 +12102,13 @@ bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) {
}
/// \brief Determine whether the given declaration is a static data member.
-static bool isStaticDataMember(Decl *D) {
- VarDecl *Var = dyn_cast_or_null<VarDecl>(D);
- if (!Var)
- return false;
-
- return Var->isStaticDataMember();
+static bool isStaticDataMember(const Decl *D) {
+ if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D))
+ return Var->isStaticDataMember();
+
+ return false;
}
+
/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse
/// an initializer for the out-of-line declaration 'Dcl'. The scope
/// is a fresh scope pushed for just this purpose.
@@ -11744,19 +12251,14 @@ bool Sema::DefineUsedVTables() {
// vtable even though we're using it.
const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(Class);
if (KeyFunction && !KeyFunction->hasBody()) {
- switch (KeyFunction->getTemplateSpecializationKind()) {
- case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
- case TSK_ExplicitInstantiationDeclaration:
- // The key function is in another translation unit.
- DefineVTable = false;
- break;
-
- case TSK_ExplicitInstantiationDefinition:
- case TSK_ImplicitInstantiation:
- // We will be instantiating the key function.
- break;
- }
+ // The key function is in another translation unit.
+ DefineVTable = false;
+ TemplateSpecializationKind TSK =
+ KeyFunction->getTemplateSpecializationKind();
+ assert(TSK != TSK_ExplicitInstantiationDefinition &&
+ TSK != TSK_ImplicitInstantiation &&
+ "Instantiations don't have key functions");
+ (void)TSK;
} else if (!KeyFunction) {
// If we have a class with no key function that is the subject
// of an explicit instantiation declaration, suppress the
@@ -11799,7 +12301,7 @@ bool Sema::DefineUsedVTables() {
Consumer.HandleVTable(Class, VTablesUsed[Canonical]);
// Optionally warn if we're emitting a weak vtable.
- if (Class->hasExternalLinkage() &&
+ if (Class->isExternallyVisible() &&
Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
const FunctionDecl *KeyFunctionDef = 0;
if (!KeyFunction ||
@@ -11920,8 +12422,6 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
llvm::SmallSet<CXXConstructorDecl*, 4> &Invalid,
llvm::SmallSet<CXXConstructorDecl*, 4> &Current,
Sema &S) {
- llvm::SmallSet<CXXConstructorDecl*, 4>::iterator CI = Current.begin(),
- CE = Current.end();
if (Ctor->isInvalidDecl())
return;
@@ -11946,8 +12446,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
// We know that beyond here, we aren't chaining into a cycle.
if (!Target || !Target->isDelegatingConstructor() ||
Target->isInvalidDecl() || Valid.count(TCanonical)) {
- for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI)
- Valid.insert(*CI);
+ Valid.insert(Current.begin(), Current.end());
Current.clear();
// We've hit a cycle.
} else if (TCanonical == Canonical || Invalid.count(TCanonical) ||
@@ -11974,8 +12473,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
}
}
- for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI)
- Invalid.insert(*CI);
+ Invalid.insert(Current.begin(), Current.end());
Current.clear();
} else {
DelegatingCycleHelper(Target, Valid, Invalid, Current, S);
@@ -11986,16 +12484,15 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
void Sema::CheckDelegatingCtorCycles() {
llvm::SmallSet<CXXConstructorDecl*, 4> Valid, Invalid, Current;
- llvm::SmallSet<CXXConstructorDecl*, 4>::iterator CI = Current.begin(),
- CE = Current.end();
-
for (DelegatingCtorDeclsType::iterator
I = DelegatingCtorDecls.begin(ExternalSource),
E = DelegatingCtorDecls.end();
I != E; ++I)
DelegatingCycleHelper(*I, Valid, Invalid, Current, *this);
- for (CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI)
+ for (llvm::SmallSet<CXXConstructorDecl *, 4>::iterator CI = Invalid.begin(),
+ CE = Invalid.end();
+ CI != CE; ++CI)
(*CI)->setInvalidDecl();
}
@@ -12211,8 +12708,7 @@ Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
if (D->hasAttr<CUDADeviceAttr>()) {
if (D->hasAttr<CUDAHostAttr>())
return CFT_HostDevice;
- else
- return CFT_Device;
+ return CFT_Device;
}
return CFT_Host;
OpenPOWER on IntegriCloud