r274049 - P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Alex L via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 23 11:07:55 PDT 2016
Hi Richard,
I think that this commit has caused a regression that's tracked by PR30274.
I'll try working on a fix for it.
Alex
On 28 June 2016 at 12:03, Richard Smith via cfe-commits <
cfe-commits at lists.llvm.org> wrote:
> Author: rsmith
> Date: Tue Jun 28 14:03:57 2016
> New Revision: 274049
>
> URL: http://llvm.org/viewvc/llvm-project?rev=274049&view=rev
> Log:
> P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
>
> Replace inheriting constructors implementation with new approach, voted
> into
> C++ last year as a DR against C++11.
>
> Instead of synthesizing a set of derived class constructors for each
> inherited
> base class constructor, we make the constructors of the base class visible
> to
> constructor lookup in the derived class, using the normal rules for
> using-declarations.
>
> For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl
> derived
> class that tracks the requisite additional information. We create shadow
> constructors (not found by name lookup) in the derived class to model the
> actual initialization, and have a new expression node,
> CXXInheritedCtorInitExpr, to model the initialization of a base class from
> such
> a constructor. (This initialization is special because it performs real
> perfect
> forwarding of arguments.)
>
> In cases where argument forwarding is not possible (for inalloca calls,
> variadic calls, and calls with callee parameter cleanup), the shadow
> inheriting
> constructor is not emitted and instead we directly emit the initialization
> code
> into the caller of the inherited constructor.
>
> Note that this new model is not perfectly compatible with the old model in
> some
> corner cases. In particular:
> * if B inherits a private constructor from A, and C uses that constructor
> to
> construct a B, then we previously required that A befriends B and B
> befriends C, but the new rules require A to befriend C directly, and
> * if a derived class has its own constructors (and so its implicit default
> constructor is suppressed), it may still inherit a default constructor
> from
> a base class
>
> Added:
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p15.cpp
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p18.cpp
> cfe/trunk/test/CXX/special/class.init/class.inhctor.init/
> cfe/trunk/test/CXX/special/class.init/class.inhctor.init/p1.cpp
> cfe/trunk/test/CXX/special/class.init/class.inhctor.init/p2.cpp
> Modified:
> cfe/trunk/include/clang/AST/ASTMutationListener.h
> cfe/trunk/include/clang/AST/Decl.h
> cfe/trunk/include/clang/AST/DeclCXX.h
> cfe/trunk/include/clang/AST/ExprCXX.h
> cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> cfe/trunk/include/clang/Basic/DeclNodes.td
> cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> cfe/trunk/include/clang/Basic/StmtNodes.td
> cfe/trunk/include/clang/Sema/Overload.h
> cfe/trunk/include/clang/Sema/Sema.h
> cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> cfe/trunk/lib/AST/ASTDumper.cpp
> cfe/trunk/lib/AST/DeclBase.cpp
> cfe/trunk/lib/AST/DeclCXX.cpp
> cfe/trunk/lib/AST/Expr.cpp
> cfe/trunk/lib/AST/ExprClassification.cpp
> cfe/trunk/lib/AST/ExprConstant.cpp
> cfe/trunk/lib/AST/ItaniumMangle.cpp
> cfe/trunk/lib/AST/NestedNameSpecifier.cpp
> cfe/trunk/lib/AST/StmtPrinter.cpp
> cfe/trunk/lib/AST/StmtProfile.cpp
> cfe/trunk/lib/CodeGen/CGCall.cpp
> cfe/trunk/lib/CodeGen/CGClass.cpp
> cfe/trunk/lib/CodeGen/CGDecl.cpp
> cfe/trunk/lib/CodeGen/CGExprAgg.cpp
> cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
> cfe/trunk/lib/CodeGen/CodeGenFunction.h
> cfe/trunk/lib/CodeGen/CodeGenModule.cpp
> cfe/trunk/lib/CodeGen/CodeGenTypes.h
> cfe/trunk/lib/Sema/SemaAccess.cpp
> cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
> cfe/trunk/lib/Sema/SemaExpr.cpp
> cfe/trunk/lib/Sema/SemaExprCXX.cpp
> cfe/trunk/lib/Sema/SemaInit.cpp
> cfe/trunk/lib/Sema/SemaLookup.cpp
> cfe/trunk/lib/Sema/SemaOverload.cpp
> cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
> cfe/trunk/lib/Sema/TreeTransform.h
> cfe/trunk/lib/Serialization/ASTCommon.cpp
> cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
> cfe/trunk/lib/Serialization/ASTWriter.cpp
> cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
> cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
> cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
> cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.
> qual/class.qual/p2.cpp
> cfe/trunk/test/CXX/basic/basic.types/p10.cpp
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp
> cfe/trunk/test/CXX/drs/dr15xx.cpp
> cfe/trunk/test/CXX/drs/dr16xx.cpp
> cfe/trunk/test/CXX/drs/dr17xx.cpp
> cfe/trunk/test/CXX/drs/dr19xx.cpp
> cfe/trunk/test/CXX/except/except.spec/p14.cpp
> cfe/trunk/test/CXX/special/class.inhctor/p1.cpp
> cfe/trunk/test/CXX/special/class.inhctor/p2.cpp
> cfe/trunk/test/CXX/special/class.inhctor/p3.cpp
> cfe/trunk/test/CXX/special/class.inhctor/p4.cpp
> cfe/trunk/test/CXX/special/class.inhctor/p7.cpp
> cfe/trunk/test/CXX/special/class.inhctor/p8.cpp
> cfe/trunk/test/CodeGenCXX/inheriting-constructor.cpp
> cfe/trunk/test/PCH/cxx11-inheriting-ctors.cpp
> cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
> cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp
> cfe/trunk/tools/libclang/CIndex.cpp
> cfe/trunk/tools/libclang/CXCursor.cpp
> cfe/trunk/www/cxx_status.html
>
> Modified: cfe/trunk/include/clang/AST/ASTMutationListener.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/AST/ASTMutationListener.h?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/AST/ASTMutationListener.h (original)
> +++ cfe/trunk/include/clang/AST/ASTMutationListener.h Tue Jun 28 14:03:57
> 2016
> @@ -17,6 +17,7 @@ namespace clang {
> class Attr;
> class ClassTemplateDecl;
> class ClassTemplateSpecializationDecl;
> + class ConstructorUsingShadowDecl;
> class CXXDestructorDecl;
> class CXXRecordDecl;
> class Decl;
>
> Modified: cfe/trunk/include/clang/AST/Decl.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/AST/Decl.h?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/AST/Decl.h (original)
> +++ cfe/trunk/include/clang/AST/Decl.h Tue Jun 28 14:03:57 2016
> @@ -387,6 +387,7 @@ public:
> NamedDecl *getUnderlyingDecl() {
> // Fast-path the common case.
> if (this->getKind() != UsingShadow &&
> + this->getKind() != ConstructorUsingShadow &&
> this->getKind() != ObjCCompatibleAlias &&
> this->getKind() != NamespaceAlias)
> return this;
>
> Modified: cfe/trunk/include/clang/AST/DeclCXX.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/AST/DeclCXX.h?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/AST/DeclCXX.h (original)
> +++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Jun 28 14:03:57 2016
> @@ -29,6 +29,7 @@ namespace clang {
>
> class ClassTemplateDecl;
> class ClassTemplateSpecializationDecl;
> +class ConstructorUsingShadowDecl;
> class CXXBasePath;
> class CXXBasePaths;
> class CXXConstructorDecl;
> @@ -1298,7 +1299,7 @@ public:
> }
>
> /// \brief Determine whether this class has a using-declaration that
> names
> - /// a base class constructor.
> + /// a user-declared base class constructor.
> bool hasInheritedConstructor() const {
> return data().HasInheritedConstructor;
> }
> @@ -2153,6 +2154,23 @@ public:
> friend TrailingObjects;
> };
>
> +/// Description of a constructor that was inherited from a base class.
> +class InheritedConstructor {
> + ConstructorUsingShadowDecl *Shadow;
> + CXXConstructorDecl *BaseCtor;
> +
> +public:
> + InheritedConstructor() : Shadow(), BaseCtor() {}
> + InheritedConstructor(ConstructorUsingShadowDecl *Shadow,
> + CXXConstructorDecl *BaseCtor)
> + : Shadow(Shadow), BaseCtor(BaseCtor) {}
> +
> + explicit operator bool() const { return Shadow; }
> +
> + ConstructorUsingShadowDecl *getShadowDecl() const { return Shadow; }
> + CXXConstructorDecl *getConstructor() const { return BaseCtor; }
> +};
> +
> /// \brief Represents a C++ constructor within a class.
> ///
> /// For example:
> @@ -2163,41 +2181,51 @@ public:
> /// explicit X(int); // represented by a CXXConstructorDecl.
> /// };
> /// \endcode
> -class CXXConstructorDecl : public CXXMethodDecl {
> +class CXXConstructorDecl final
> + : public CXXMethodDecl,
> + private llvm::TrailingObjects<CXXConstructorDecl,
> InheritedConstructor> {
> void anchor() override;
>
> /// \name Support for base and member initializers.
> /// \{
> /// \brief The arguments used to initialize the base or member.
> LazyCXXCtorInitializersPtr CtorInitializers;
> - unsigned NumCtorInitializers : 31;
> + unsigned NumCtorInitializers : 30;
> /// \}
>
> /// \brief Whether this constructor declaration has the \c explicit
> keyword
> /// specified.
> unsigned IsExplicitSpecified : 1;
>
> + /// \brief Whether this constructor declaration is an
> implicitly-declared
> + /// inheriting constructor.
> + unsigned IsInheritingConstructor : 1;
> +
> CXXConstructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation
> StartLoc,
> const DeclarationNameInfo &NameInfo,
> QualType T, TypeSourceInfo *TInfo,
> bool isExplicitSpecified, bool isInline,
> - bool isImplicitlyDeclared, bool isConstexpr)
> + bool isImplicitlyDeclared, bool isConstexpr,
> + InheritedConstructor Inherited)
> : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo,
> SC_None, isInline, isConstexpr, SourceLocation()),
> CtorInitializers(nullptr), NumCtorInitializers(0),
> - IsExplicitSpecified(isExplicitSpecified) {
> + IsExplicitSpecified(isExplicitSpecified),
> + IsInheritingConstructor((bool)Inherited) {
> setImplicit(isImplicitlyDeclared);
> + if (Inherited)
> + *getTrailingObjects<InheritedConstructor>() = Inherited;
> }
>
> public:
> - static CXXConstructorDecl *CreateDeserialized(ASTContext &C, unsigned
> ID);
> - static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
> - SourceLocation StartLoc,
> - const DeclarationNameInfo &NameInfo,
> - QualType T, TypeSourceInfo *TInfo,
> - bool isExplicit,
> - bool isInline, bool
> isImplicitlyDeclared,
> - bool isConstexpr);
> + static CXXConstructorDecl *CreateDeserialized(ASTContext &C, unsigned
> ID,
> + bool InheritsConstructor);
> + static CXXConstructorDecl *
> + Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
> + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo
> *TInfo,
> + bool isExplicit, bool isInline, bool isImplicitlyDeclared,
> + bool isConstexpr,
> + InheritedConstructor Inherited = InheritedConstructor());
>
> /// \brief Determine whether this constructor declaration has the
> /// \c explicit keyword specified.
> @@ -2344,11 +2372,15 @@ public:
> /// an object.
> bool isSpecializationCopyingObject() const;
>
> - /// \brief Get the constructor that this inheriting constructor is
> based on.
> - const CXXConstructorDecl *getInheritedConstructor() const;
> + /// \brief Determine whether this is an implicit constructor
> synthesized to
> + /// model a call to a constructor inherited from a base class.
> + bool isInheritingConstructor() const { return IsInheritingConstructor; }
>
> - /// \brief Set the constructor that this inheriting constructor is
> based on.
> - void setInheritedConstructor(const CXXConstructorDecl *BaseCtor);
> + /// \brief Get the constructor that this inheriting constructor is
> based on.
> + InheritedConstructor getInheritedConstructor() const {
> + return IsInheritingConstructor ? *getTrailingObjects<
> InheritedConstructor>()
> + : InheritedConstructor();
> + }
>
> CXXConstructorDecl *getCanonicalDecl() override {
> return cast<CXXConstructorDecl>(FunctionDecl::getCanonicalDecl());
> @@ -2363,6 +2395,7 @@ public:
>
> friend class ASTDeclReader;
> friend class ASTDeclWriter;
> + friend TrailingObjects;
> };
>
> /// \brief Represents a C++ destructor within a class.
> @@ -2807,18 +2840,6 @@ class UsingShadowDecl : public NamedDecl
> NamedDecl *UsingOrNextShadow;
> friend class UsingDecl;
>
> - UsingShadowDecl(ASTContext &C, DeclContext *DC, SourceLocation Loc,
> - UsingDecl *Using, NamedDecl *Target)
> - : NamedDecl(UsingShadow, DC, Loc, DeclarationName()),
> - redeclarable_base(C), Underlying(Target),
> - UsingOrNextShadow(reinterpret_cast<NamedDecl *>(Using)) {
> - if (Target) {
> - setDeclName(Target->getDeclName());
> - IdentifierNamespace = Target->getIdentifierNamespace();
> - }
> - setImplicit();
> - }
> -
> typedef Redeclarable<UsingShadowDecl> redeclarable_base;
> UsingShadowDecl *getNextRedeclarationImpl() override {
> return getNextRedeclaration();
> @@ -2830,11 +2851,16 @@ class UsingShadowDecl : public NamedDecl
> return getMostRecentDecl();
> }
>
> +protected:
> + UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC, SourceLocation
> Loc,
> + UsingDecl *Using, NamedDecl *Target);
> + UsingShadowDecl(Kind K, ASTContext &C, EmptyShell);
> +
> public:
> static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC,
> SourceLocation Loc, UsingDecl *Using,
> NamedDecl *Target) {
> - return new (C, DC) UsingShadowDecl(C, DC, Loc, Using, Target);
> + return new (C, DC) UsingShadowDecl(UsingShadow, C, DC, Loc, Using,
> Target);
> }
>
> static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID);
> @@ -2846,6 +2872,7 @@ public:
> using redeclarable_base::redecls;
> using redeclarable_base::getPreviousDecl;
> using redeclarable_base::getMostRecentDecl;
> + using redeclarable_base::isFirstDecl;
>
> UsingShadowDecl *getCanonicalDecl() override {
> return getFirstDecl();
> @@ -2876,7 +2903,125 @@ public:
> }
>
> static bool classof(const Decl *D) { return classofKind(D->getKind()); }
> - static bool classofKind(Kind K) { return K == Decl::UsingShadow; }
> + static bool classofKind(Kind K) {
> + return K == Decl::UsingShadow || K == Decl::ConstructorUsingShadow;
> + }
> +
> + friend class ASTDeclReader;
> + friend class ASTDeclWriter;
> +};
> +
> +/// \brief Represents a shadow constructor declaration introduced into a
> +/// class by a C++11 using-declaration that names a constructor.
> +///
> +/// For example:
> +/// \code
> +/// struct Base { Base(int); };
> +/// struct Derived {
> +/// using Base::Base; // creates a UsingDecl and a
> ConstructorUsingShadowDecl
> +/// };
> +/// \endcode
> +class ConstructorUsingShadowDecl final : public UsingShadowDecl {
> + void anchor() override;
> +
> + /// \brief If this constructor using declaration inherted the
> constructor
> + /// from an indirect base class, this is the ConstructorUsingShadowDecl
> + /// in the named direct base class from which the declaration was
> inherited.
> + ConstructorUsingShadowDecl *NominatedBaseClassShadowDecl;
> +
> + /// \brief If this constructor using declaration inherted the
> constructor
> + /// from an indirect base class, this is the ConstructorUsingShadowDecl
> + /// that will be used to construct the unique direct or virtual base
> class
> + /// that receives the constructor arguments.
> + ConstructorUsingShadowDecl *ConstructedBaseClassShadowDecl;
> +
> + /// \brief \c true if the constructor ultimately named by this using
> shadow
> + /// declaration is within a virtual base class subobject of the class
> that
> + /// contains this declaration.
> + unsigned IsVirtual : 1;
> +
> + ConstructorUsingShadowDecl(ASTContext &C, DeclContext *DC,
> SourceLocation Loc,
> + UsingDecl *Using, NamedDecl *Target,
> + bool TargetInVirtualBase)
> + : UsingShadowDecl(ConstructorUsingShadow, C, DC, Loc, Using,
> + Target->getUnderlyingDecl()),
> + NominatedBaseClassShadowDecl(
> + dyn_cast<ConstructorUsingShadowDecl>(Target)),
> + ConstructedBaseClassShadowDecl(NominatedBaseClassShadowDecl),
> + IsVirtual(TargetInVirtualBase) {
> + // If we found a constructor for a non-virtual base class, but it
> chains to
> + // a constructor for a virtual base, we should directly call the
> virtual
> + // base constructor instead.
> + // FIXME: This logic belongs in Sema.
> + if (!TargetInVirtualBase && NominatedBaseClassShadowDecl &&
> + NominatedBaseClassShadowDecl->constructsVirtualBase()) {
> + ConstructedBaseClassShadowDecl =
> + NominatedBaseClassShadowDecl->ConstructedBaseClassShadowDecl;
> + IsVirtual = true;
> + }
> + }
> + ConstructorUsingShadowDecl(ASTContext &C, EmptyShell Empty)
> + : UsingShadowDecl(ConstructorUsingShadow, C, Empty) {}
> +
> +public:
> + static ConstructorUsingShadowDecl *Create(ASTContext &C, DeclContext
> *DC,
> + SourceLocation Loc,
> + UsingDecl *Using, NamedDecl
> *Target,
> + bool IsVirtual);
> + static ConstructorUsingShadowDecl *CreateDeserialized(ASTContext &C,
> + unsigned ID);
> +
> + /// Returns the parent of this using shadow declaration, which
> + /// is the class in which this is declared.
> + //@{
> + const CXXRecordDecl *getParent() const {
> + return cast<CXXRecordDecl>(getDeclContext());
> + }
> + CXXRecordDecl *getParent() {
> + return cast<CXXRecordDecl>(getDeclContext());
> + }
> + //@}
> +
> + /// \brief Get the inheriting constructor declaration for the direct
> base
> + /// class from which this using shadow declaration was inherited, if
> there is
> + /// one. This can be different for each redeclaration of the same
> shadow decl.
> + ConstructorUsingShadowDecl *getNominatedBaseClassShadowDecl() const {
> + return NominatedBaseClassShadowDecl;
> + }
> +
> + /// \brief Get the inheriting constructor declaration for the base class
> + /// for which we don't have an explicit initializer, if there is one.
> + ConstructorUsingShadowDecl *getConstructedBaseClassShadowDecl() const {
> + return ConstructedBaseClassShadowDecl;
> + }
> +
> + /// \brief Get the base class that was named in the using declaration.
> This
> + /// can be different for each redeclaration of this same shadow decl.
> + CXXRecordDecl *getNominatedBaseClass() const;
> +
> + /// \brief Get the base class whose constructor or constructor shadow
> + /// declaration is passed the constructor arguments.
> + CXXRecordDecl *getConstructedBaseClass() const {
> + return cast<CXXRecordDecl>((ConstructedBaseClassShadowDecl
> + ? ConstructedBaseClassShadowDecl
> + : getTargetDecl())
> + ->getDeclContext());
> + }
> +
> + /// \brief Returns \c true if the constructed base class is a virtual
> base
> + /// class subobject of this declaration's class.
> + bool constructsVirtualBase() const {
> + return IsVirtual;
> + }
> +
> + /// \brief Get the constructor or constructor template in the derived
> class
> + /// correspnding to this using shadow declaration, if it has been
> implicitly
> + /// declared already.
> + CXXConstructorDecl *getConstructor() const;
> + void setConstructor(NamedDecl *Ctor);
> +
> + static bool classof(const Decl *D) { return classofKind(D->getKind()); }
> + static bool classofKind(Kind K) { return K == ConstructorUsingShadow; }
>
> friend class ASTDeclReader;
> friend class ASTDeclWriter;
>
> Modified: cfe/trunk/include/clang/AST/ExprCXX.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/AST/ExprCXX.h?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/AST/ExprCXX.h (original)
> +++ cfe/trunk/include/clang/AST/ExprCXX.h Tue Jun 28 14:03:57 2016
> @@ -1318,6 +1318,73 @@ public:
> friend class ASTStmtReader;
> };
>
> +/// \brief Represents a call to an inherited base class constructor from
> an
> +/// inheriting constructor. This call implicitly forwards the arguments
> from
> +/// the enclosing context (an inheriting constructor) to the specified
> inherited
> +/// base class constructor.
> +class CXXInheritedCtorInitExpr : public Expr {
> +private:
> + CXXConstructorDecl *Constructor;
> +
> + /// The location of the using declaration.
> + SourceLocation Loc;
> +
> + /// Whether this is the construction of a virtual base.
> + unsigned ConstructsVirtualBase : 1;
> +
> + /// Whether the constructor is inherited from a virtual base class of
> the
> + /// class that we construct.
> + unsigned InheritedFromVirtualBase : 1;
> +
> +public:
> + /// \brief Construct a C++ inheriting construction expression.
> + CXXInheritedCtorInitExpr(SourceLocation Loc, QualType T,
> + CXXConstructorDecl *Ctor, bool
> ConstructsVirtualBase,
> + bool InheritedFromVirtualBase)
> + : Expr(CXXInheritedCtorInitExprClass, T, VK_RValue, OK_Ordinary,
> false,
> + false, false, false),
> + Constructor(Ctor), Loc(Loc),
> + ConstructsVirtualBase(ConstructsVirtualBase),
> + InheritedFromVirtualBase(InheritedFromVirtualBase) {
> + assert(!T->isDependentType());
> + }
> +
> + /// \brief Construct an empty C++ inheriting construction expression.
> + explicit CXXInheritedCtorInitExpr(EmptyShell Empty)
> + : Expr(CXXInheritedCtorInitExprClass, Empty), Constructor(nullptr),
> + ConstructsVirtualBase(false), InheritedFromVirtualBase(false) {}
> +
> + /// \brief Get the constructor that this expression will call.
> + CXXConstructorDecl *getConstructor() const { return Constructor; }
> +
> + /// \brief Determine whether this constructor is actually constructing
> + /// a base class (rather than a complete object).
> + bool constructsVBase() const { return ConstructsVirtualBase; }
> + CXXConstructExpr::ConstructionKind getConstructionKind() const {
> + return ConstructsVirtualBase ? CXXConstructExpr::CK_VirtualBase
> + : CXXConstructExpr::CK_NonVirtualBase;
> + }
> +
> + /// \brief Determine whether the inherited constructor is inherited
> from a
> + /// virtual base of the object we construct. If so, we are not
> responsible
> + /// for calling the inherited constructor (the complete object
> constructor
> + /// does that), and so we don't need to pass any arguments.
> + bool inheritedFromVBase() const { return InheritedFromVirtualBase; }
> +
> + SourceLocation getLocation() const LLVM_READONLY { return Loc; }
> + SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
> + SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
> +
> + static bool classof(const Stmt *T) {
> + return T->getStmtClass() == CXXInheritedCtorInitExprClass;
> + }
> + child_range children() {
> + return child_range(child_iterator(), child_iterator());
> + }
> +
> + friend class ASTStmtReader;
> +};
> +
> /// \brief Represents an explicit C++ type conversion that uses
> "functional"
> /// notation (C++ [expr.type.conv]).
> ///
>
> Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/AST/RecursiveASTVisitor.h?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
> +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Jun 28 14:03:57
> 2016
> @@ -1466,6 +1466,8 @@ DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
>
> DEF_TRAVERSE_DECL(UsingShadowDecl, {})
>
> +DEF_TRAVERSE_DECL(ConstructorUsingShadowDecl, {})
> +
> DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, {
> for (auto *I : D->varlists()) {
> TRY_TO(TraverseStmt(I));
> @@ -2266,6 +2268,7 @@ DEF_TRAVERSE_STMT(CXXDefaultArgExpr, {})
> DEF_TRAVERSE_STMT(CXXDefaultInitExpr, {})
> DEF_TRAVERSE_STMT(CXXDeleteExpr, {})
> DEF_TRAVERSE_STMT(ExprWithCleanups, {})
> +DEF_TRAVERSE_STMT(CXXInheritedCtorInitExpr, {})
> DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, {})
> DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, {})
> DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
>
> Modified: cfe/trunk/include/clang/Basic/DeclNodes.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Basic/DeclNodes.td?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Basic/DeclNodes.td (original)
> +++ cfe/trunk/include/clang/Basic/DeclNodes.td Tue Jun 28 14:03:57 2016
> @@ -66,6 +66,7 @@ def Named : Decl<1>;
> def BuiltinTemplate : DDecl<Template>;
> def Using : DDecl<Named>;
> def UsingShadow : DDecl<Named>;
> + def ConstructorUsingShadow : DDecl<UsingShadow>;
> def ObjCMethod : DDecl<Named>, DeclContext;
> def ObjCContainer : DDecl<Named, 1>, DeclContext;
> def ObjCCategory : DDecl<ObjCContainer>;
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/
> DiagnosticASTKinds.td?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td Tue Jun 28
> 14:03:57 2016
> @@ -26,6 +26,9 @@ def note_constexpr_lshift_discards : Not
> def note_constexpr_invalid_function : Note<
> "%select{non-constexpr|undefined}0 %select{function|constructor}1 %2
> cannot "
> "be used in a constant expression">;
> +def note_constexpr_invalid_inhctor : Note<
> + "constructor inherited from base class %0 cannot be used in a "
> + "constant expression; derived class cannot be implicitly initialized">;
> def note_constexpr_no_return : Note<
> "control reached end of constexpr function">;
> def note_constexpr_virtual_call : Note<
> @@ -141,6 +144,8 @@ def note_constexpr_calls_suppressed : No
> "(skipping %0 call%s0 in backtrace; use -fconstexpr-backtrace-limit=0
> to "
> "see all)">;
> def note_constexpr_call_here : Note<"in call to '%0'">;
> +def note_constexpr_inherited_ctor_call_here : Note<
> + "in implicit initialization for inherited constructor of %0">;
> def note_constexpr_baa_insufficient_alignment : Note<
> "%select{alignment of|offset of the aligned pointer from}0 the base
> pointee "
> "object (%1 %plural{1:byte|:bytes}1) is %select{less than|not a
> multiple of}0 the "
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/
> DiagnosticSemaKinds.td?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jun 28
> 14:03:57 2016
> @@ -381,22 +381,12 @@ def err_using_decl_nested_name_specifier
> "using declaration refers into '%0', which is not a base class of %1">;
> def err_using_decl_constructor_not_in_direct_base : Error<
> "%0 is not a direct base of %1, cannot inherit constructors">;
> -def err_using_decl_constructor_conflict : Error<
> - "cannot inherit constructor, already inherited constructor with "
> - "the same signature">;
> -def note_using_decl_constructor_conflict_current_ctor : Note<
> - "conflicting constructor">;
> -def note_using_decl_constructor_conflict_previous_ctor : Note<
> - "previous constructor">;
> -def note_using_decl_constructor_conflict_previous_using : Note<
> - "previously inherited here">;
> -def warn_using_decl_constructor_ellipsis : Warning<
> - "inheriting constructor does not inherit ellipsis">,
> - InGroup<DiagGroup<"inherited-variadic-ctor">>;
> -def note_using_decl_constructor_ellipsis : Note<
> - "constructor declared with ellipsis here">;
> def err_using_decl_can_not_refer_to_class_member : Error<
> "using declaration cannot refer to class member">;
> +def err_ambiguous_inherited_constructor : Error<
> + "constructor of %0 inherited from multiple base class subobjects">;
> +def note_ambiguous_inherited_constructor_using : Note<
> + "inherited from base class %0 here">;
> def note_using_decl_class_member_workaround : Note<
> "use %select{an alias declaration|a typedef declaration|a reference|"
> "a const variable|a constexpr variable}0 instead">;
> @@ -415,7 +405,7 @@ def err_using_decl_template_id : Error<
> "using declaration cannot refer to a template specialization">;
> def note_using_decl_target : Note<"target of using declaration">;
> def note_using_decl_conflict : Note<"conflicting declaration">;
> -def err_using_decl_redeclaration : Error<"redeclaration of using decl">;
> +def err_using_decl_redeclaration : Error<"redeclaration of using
> declaration">;
> def err_using_decl_conflict : Error<
> "target of using declaration conflicts with declaration already in
> scope">;
> def err_using_decl_conflict_reverse : Error<
> @@ -1436,11 +1426,13 @@ def note_member_synthesized_at : Note<
> "assignment operator|move assignment operator|destructor}0 for %1 first
> "
> "required here">;
> def note_inhctor_synthesized_at : Note<
> - "inheriting constructor for %0 first required here">;
> + "inherited constructor for %0 first required here">;
> def err_missing_default_ctor : Error<
> - "%select{|implicit default |inheriting }0constructor for %1 must
> explicitly "
> - "initialize the %select{base class|member}2 %3 which does not have a
> default "
> - "constructor">;
> + "%select{constructor for %1 must explicitly initialize the|"
> + "implicit default constructor for %1 must explicitly initialize the|"
> + "cannot use constructor inherited from base class %4;}0 "
> + "%select{base class|member}2 %3 %select{which|which|of %1}0 "
> + "does not have a default constructor">;
> def note_due_to_dllexported_class : Note<
> "due to '%0' being dllexported%select{|; try compiling in C++11
> mode}1">;
>
> @@ -3111,7 +3103,9 @@ def err_uninitialized_member_for_assign
> "non-static %select{reference|const}1 member %2 cannot use copy "
> "assignment operator">;
> def err_uninitialized_member_in_ctor : Error<
> - "%select{|implicit default |inheriting }0constructor for %1 must
> explicitly "
> + "%select{constructor for %1|"
> + "implicit default constructor for %1|"
> + "cannot use constructor inherited from %1:}0 must explicitly "
> "initialize the %select{reference|const}2 member %3">;
> def err_default_arg_makes_ctor_special : Error<
> "addition of default argument on redeclaration makes this constructor a
> "
> @@ -3160,7 +3154,8 @@ def note_ovl_candidate : Note<"candidate
> "is the implicit move constructor|"
> "is the implicit copy assignment operator|"
> "is the implicit move assignment operator|"
> - "is an inherited constructor}0%1"
> + "inherited constructor|"
> + "inherited constructor }0%1"
> "%select{| has different class%diff{ (expected $ but has $)|}3,4"
> "| has different number of parameters (expected %3 but has %4)"
> "| has type mismatch at %ordinal3 parameter"
> @@ -3172,7 +3167,8 @@ def note_ovl_candidate : Note<"candidate
> "%select{none|const|restrict|const and restrict|volatile|const and
> volatile"
> "|volatile and restrict|const, volatile, and restrict}4)}2">;
>
> -def note_ovl_candidate_inherited_constructor : Note<"inherited from
> here">;
> +def note_ovl_candidate_inherited_constructor : Note<
> + "constructor from base class %0 inherited here">;
> def note_ovl_candidate_illegal_constructor : Note<
> "candidate %select{constructor|template}0 ignored: "
> "instantiation %select{takes|would take}0 its own class type by
> value">;
> @@ -3232,7 +3228,8 @@ def note_ovl_candidate_arity : Note<"can
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0 %select{|template }1"
> + "inherited constructor|"
> + "inherited constructor}0 %select{|template }1"
> "not viable: requires%select{ at least| at most|}2 %3 argument%s3,
> but %4 "
> "%plural{1:was|:were}4 provided">;
>
> @@ -3243,7 +3240,8 @@ def note_ovl_candidate_arity_one : Note<
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0 %select{|template }1not viable: "
> + "inherited constructor|"
> + "inherited constructor}0 %select{|template }1not viable: "
> "%select{requires at least|allows at most single|requires single}2 "
> "argument %3, but %plural{0:no|:%4}4 arguments were provided">;
>
> @@ -3255,7 +3253,8 @@ def note_ovl_candidate_deleted : Note<
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0%1 has been "
> + "inherited constructor|"
> + "inherited constructor }0%1 has been "
> "%select{explicitly made unavailable|explicitly deleted|"
> "implicitly deleted}2">;
>
> @@ -3272,7 +3271,8 @@ def note_ovl_candidate_bad_conv_incomple
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0%1 "
> + "inherited constructor|"
> + "inherited constructor }0%1 "
> "not viable: cannot convert argument of incomplete type "
> "%diff{$ to $|to parameter type}2,3 for "
> "%select{%ordinal5 argument|object argument}4"
> @@ -3288,7 +3288,8 @@ def note_ovl_candidate_bad_list_argument
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0%1 "
> + "inherited constructor|"
> + "inherited constructor }0%1 "
> "not viable: cannot convert initializer list argument to %3">;
> def note_ovl_candidate_bad_overload : Note<"candidate "
> "%select{function|function|constructor|"
> @@ -3298,7 +3299,8 @@ def note_ovl_candidate_bad_overload : No
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0%1"
> + "inherited constructor|"
> + "inherited constructor }0%1"
> " not viable: no overload of %3 matching %2 for %ordinal4 argument">;
> def note_ovl_candidate_bad_conv : Note<"candidate "
> "%select{function|function|constructor|"
> @@ -3308,7 +3310,8 @@ def note_ovl_candidate_bad_conv : Note<"
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0%1"
> + "inherited constructor|"
> + "inherited constructor }0%1"
> " not viable: no known conversion "
> "%diff{from $ to $|from argument type to parameter type}2,3 for "
> "%select{%ordinal5 argument|object argument}4"
> @@ -3324,7 +3327,8 @@ def note_ovl_candidate_bad_arc_conv : No
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0%1"
> + "inherited constructor|"
> + "inherited constructor }0%1"
> " not viable: cannot implicitly convert argument "
> "%diff{of type $ to $|type to parameter type}2,3 for "
> "%select{%ordinal5 argument|object argument}4 under ARC">;
> @@ -3336,7 +3340,8 @@ def note_ovl_candidate_bad_lvalue : Note
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0%1"
> + "inherited constructor|"
> + "inherited constructor }0%1"
> " not viable: expects an l-value for "
> "%select{%ordinal3 argument|object argument}2">;
> def note_ovl_candidate_bad_addrspace : Note<"candidate "
> @@ -3347,7 +3352,8 @@ def note_ovl_candidate_bad_addrspace : N
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0%1 not viable: "
> + "inherited constructor|"
> + "inherited constructor }0%1 not viable: "
> "%select{%ordinal6|'this'}5 argument (%2) is in "
> "address space %3, but parameter must be in address space %4">;
> def note_ovl_candidate_bad_gc : Note<"candidate "
> @@ -3358,7 +3364,8 @@ def note_ovl_candidate_bad_gc : Note<"ca
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0%1 not viable: "
> + "inherited constructor|"
> + "inherited constructor }0%1 not viable: "
> "%select{%ordinal6|'this'}5 argument (%2) has
> %select{no|__weak|__strong}3 "
> "ownership, but parameter has %select{no|__weak|__strong}4
> ownership">;
> def note_ovl_candidate_bad_ownership : Note<"candidate "
> @@ -3369,7 +3376,8 @@ def note_ovl_candidate_bad_ownership : N
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0%1 not viable: "
> + "inherited constructor|"
> + "inherited constructor }0%1 not viable: "
> "%select{%ordinal6|'this'}5 argument (%2) has "
> "%select{no|__unsafe_unretained|__strong|__weak|__autoreleasing}3
> ownership,"
> " but parameter has %select{no|__unsafe_unretained|__strong|__weak|"
> @@ -3377,7 +3385,7 @@ def note_ovl_candidate_bad_ownership : N
> def note_ovl_candidate_bad_cvr_this : Note<"candidate "
> "%select{|function|||function|||||"
> "function (the implicit copy assignment operator)|"
> - "function (the implicit move assignment operator)|}0 not viable: "
> + "function (the implicit move assignment operator)||}0 not viable: "
> "'this' argument has type %2, but method is not marked "
> "%select{const|restrict|const or restrict|volatile|const or volatile|"
> "volatile or restrict|const, volatile, or restrict}3">;
> @@ -3389,7 +3397,8 @@ def note_ovl_candidate_bad_cvr : Note<"c
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0%1 not viable: "
> + "inherited constructor|"
> + "inherited constructor }0%1 not viable: "
> "%ordinal4 argument (%2) would lose "
> "%select{const|restrict|const and restrict|volatile|const and
> volatile|"
> "volatile and restrict|const, volatile, and restrict}3 qualifier"
> @@ -3402,7 +3411,8 @@ def note_ovl_candidate_bad_unaligned : N
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0%1 not viable: "
> + "inherited constructor|"
> + "inherited constructor }0%1 not viable: "
> "%ordinal4 argument (%2) would lose __unaligned qualifier">;
> def note_ovl_candidate_bad_base_to_derived_conv : Note<"candidate "
> "%select{function|function|constructor|"
> @@ -3412,20 +3422,23 @@ def note_ovl_candidate_bad_base_to_deriv
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0%1"
> - " not viable: cannot %select{convert from|convert from|bind}2 "
> + "inherited constructor|"
> + "inherited constructor }0%1 not viable: "
> + "cannot %select{convert from|convert from|bind}2 "
> "%select{base class pointer|superclass|base class object of type}2 %3
> to "
> "%select{derived class pointer|subclass|derived class reference}2 %4
> for "
> "%ordinal5 argument">;
> def note_ovl_candidate_bad_target : Note<
> "candidate %select{function|function|constructor|"
> - "function |function |constructor |"
> + "function|function|constructor|"
> "constructor (the implicit default constructor)|"
> "constructor (the implicit copy constructor)|"
> "constructor (the implicit move constructor)|"
> "function (the implicit copy assignment operator)|"
> "function (the implicit move assignment operator)|"
> - "constructor (inherited)}0 not viable: call to "
> + "inherited constructor|"
> + "inherited constructor}0 not viable: "
> + "call to "
> "%select{__device__|__global__|__host__|__host__
> __device__|invalid}1 function from"
> " %select{__device__|__global__|__host__|__host__
> __device__|invalid}2 function">;
> def note_implicit_member_target_infer_collision : Note<
> @@ -4237,8 +4250,6 @@ def note_implicitly_deleted : Note<
> "explicitly defaulted function was implicitly deleted here">;
> def note_inherited_deleted_here : Note<
> "deleted constructor was inherited here">;
> -def note_cannot_inherit : Note<
> - "constructor cannot be inherited">;
> def warn_not_enough_argument : Warning<
> "not enough variable arguments in %0 declaration to fit a sentinel">,
> InGroup<Sentinel>;
>
> Modified: cfe/trunk/include/clang/Basic/StmtNodes.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Basic/StmtNodes.td?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Basic/StmtNodes.td (original)
> +++ cfe/trunk/include/clang/Basic/StmtNodes.td Tue Jun 28 14:03:57 2016
> @@ -126,6 +126,7 @@ def ArrayTypeTraitExpr : DStmt<Expr>;
> def ExpressionTraitExpr : DStmt<Expr>;
> def DependentScopeDeclRefExpr : DStmt<Expr>;
> def CXXConstructExpr : DStmt<Expr>;
> +def CXXInheritedCtorInitExpr : DStmt<Expr>;
> def CXXBindTemporaryExpr : DStmt<Expr>;
> def ExprWithCleanups : DStmt<Expr>;
> def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>;
>
> Modified: cfe/trunk/include/clang/Sema/Overload.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Sema/Overload.h?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Sema/Overload.h (original)
> +++ cfe/trunk/include/clang/Sema/Overload.h Tue Jun 28 14:03:57 2016
> @@ -803,6 +803,7 @@ namespace clang {
> DeclAccessPair FoundDecl;
> CXXConstructorDecl *Constructor;
> FunctionTemplateDecl *ConstructorTmpl;
> + explicit operator bool() const { return Constructor; }
> };
> // FIXME: Add an AddOverloadCandidate / AddTemplateOverloadCandidate
> overload
> // that takes one of these.
> @@ -818,7 +819,7 @@ namespace clang {
> Info.ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
> if (Info.ConstructorTmpl)
> D = Info.ConstructorTmpl->getTemplatedDecl();
> - Info.Constructor = cast<CXXConstructorDecl>(D);
> + Info.Constructor = dyn_cast<CXXConstructorDecl>(D);
> return Info;
> }
> } // end namespace clang
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Sema/Sema.h?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Tue Jun 28 14:03:57 2016
> @@ -4256,6 +4256,13 @@ public:
>
> bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
>
> + /// Given a derived-class using shadow declaration for a constructor
> and the
> + /// correspnding base class constructor, find or create the implicit
> + /// synthesized derived class constructor to use for this
> initialization.
> + CXXConstructorDecl *
> + findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl
> *BaseCtor,
> + ConstructorUsingShadowDecl *DerivedShadow);
> +
> Decl *ActOnUsingDeclaration(Scope *CurScope,
> AccessSpecifier AS,
> bool HasUsingKeyword,
> @@ -4422,7 +4429,8 @@ public:
> /// \brief Determine what sort of exception specification an inheriting
> /// constructor of a class will have.
> ImplicitExceptionSpecification
> - ComputeInheritingCtorExceptionSpec(CXXConstructorDecl *CD);
> + ComputeInheritingCtorExceptionSpec(SourceLocation Loc,
> + CXXConstructorDecl *CD);
>
> /// \brief Evaluate the implicit exception specification for a defaulted
> /// special member function.
> @@ -4491,12 +4499,6 @@ public:
> void AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
> CXXDestructorDecl *Destructor);
>
> - /// \brief Declare all inheriting constructors for the given class.
> - ///
> - /// \param ClassDecl The class declaration into which the inheriting
> - /// constructors will be added.
> - void DeclareInheritingConstructors(CXXRecordDecl *ClassDecl);
> -
> /// \brief Define the specified inheriting constructor.
> void DefineInheritingConstructor(SourceLocation UseLoc,
> CXXConstructorDecl *Constructor);
> @@ -5562,13 +5564,13 @@ public:
> bool Diagnose = true);
> AccessResult CheckConstructorAccess(SourceLocation Loc,
> CXXConstructorDecl *D,
> + DeclAccessPair FoundDecl,
> const InitializedEntity &Entity,
> - AccessSpecifier Access,
> bool IsCopyBindingRefToTemp =
> false);
> AccessResult CheckConstructorAccess(SourceLocation Loc,
> CXXConstructorDecl *D,
> + DeclAccessPair FoundDecl,
> const InitializedEntity &Entity,
> - AccessSpecifier Access,
> const PartialDiagnostic &PDiag);
> AccessResult CheckDestructorAccess(SourceLocation Loc,
> CXXDestructorDecl *Dtor,
>
> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Serialization/ASTBitCodes.h?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Jun 28
> 14:03:57 2016
> @@ -1083,6 +1083,8 @@ namespace clang {
> DECL_USING,
> /// \brief A UsingShadowDecl record.
> DECL_USING_SHADOW,
> + /// \brief A ConstructorUsingShadowDecl record.
> + DECL_CONSTRUCTOR_USING_SHADOW,
> /// \brief A UsingDirecitveDecl record.
> DECL_USING_DIRECTIVE,
> /// \brief An UnresolvedUsingValueDecl record.
> @@ -1097,6 +1099,8 @@ namespace clang {
> DECL_CXX_METHOD,
> /// \brief A CXXConstructorDecl record.
> DECL_CXX_CONSTRUCTOR,
> + /// \brief A CXXConstructorDecl record for an inherited constructor.
> + DECL_CXX_INHERITED_CONSTRUCTOR,
> /// \brief A CXXDestructorDecl record.
> DECL_CXX_DESTRUCTOR,
> /// \brief A CXXConversionDecl record.
> @@ -1360,6 +1364,8 @@ namespace clang {
> EXPR_CXX_MEMBER_CALL,
> /// \brief A CXXConstructExpr record.
> EXPR_CXX_CONSTRUCT,
> + /// \brief A CXXInheritedCtorInitExpr record.
> + EXPR_CXX_INHERITED_CTOR_INIT,
> /// \brief A CXXTemporaryObjectExpr record.
> EXPR_CXX_TEMPORARY_OBJECT,
> /// \brief A CXXStaticCastExpr record.
>
> Modified: cfe/trunk/lib/AST/ASTDumper.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> ASTDumper.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/ASTDumper.cpp (original)
> +++ cfe/trunk/lib/AST/ASTDumper.cpp Tue Jun 28 14:03:57 2016
> @@ -474,6 +474,7 @@ namespace {
> void VisitUnresolvedUsingTypenameDecl(const
> UnresolvedUsingTypenameDecl *D);
> void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl
> *D);
> void VisitUsingShadowDecl(const UsingShadowDecl *D);
> + void VisitConstructorUsingShadowDecl(const
> ConstructorUsingShadowDecl *D);
> void VisitLinkageSpecDecl(const LinkageSpecDecl *D);
> void VisitAccessSpecDecl(const AccessSpecDecl *D);
> void VisitFriendDecl(const FriendDecl *D);
> @@ -713,6 +714,12 @@ void ASTDumper::dumpTypeAsChild(const Ty
> }
>
> void ASTDumper::dumpBareDeclRef(const Decl *D) {
> + if (!D) {
> + ColorScope Color(*this, NullColor);
> + OS << "<<<NULL>>>";
> + return;
> + }
> +
> {
> ColorScope Color(*this, DeclKindNameColor);
> OS << D->getDeclKindName();
> @@ -1491,6 +1498,31 @@ void ASTDumper::VisitUsingShadowDecl(con
> dumpTypeAsChild(TD->getTypeForDecl());
> }
>
> +void ASTDumper::VisitConstructorUsingShadowDecl(
> + const ConstructorUsingShadowDecl *D) {
> + if (D->constructsVirtualBase())
> + OS << " virtual";
> +
> + dumpChild([=] {
> + OS << "target ";
> + dumpBareDeclRef(D->getTargetDecl());
> + });
> +
> + dumpChild([=] {
> + OS << "nominated ";
> + dumpBareDeclRef(D->getNominatedBaseClass());
> + OS << ' ';
> + dumpBareDeclRef(D->getNominatedBaseClassShadowDecl());
> + });
> +
> + dumpChild([=] {
> + OS << "constructed ";
> + dumpBareDeclRef(D->getConstructedBaseClass());
> + OS << ' ';
> + dumpBareDeclRef(D->getConstructedBaseClassShadowDecl());
> + });
> +}
> +
> void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
> switch (D->getLanguage()) {
> case LinkageSpecDecl::lang_c: OS << " C"; break;
>
> Modified: cfe/trunk/lib/AST/DeclBase.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> DeclBase.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/DeclBase.cpp (original)
> +++ cfe/trunk/lib/AST/DeclBase.cpp Tue Jun 28 14:03:57 2016
> @@ -594,6 +594,7 @@ unsigned Decl::getIdentifierNamespaceFor
> case Function:
> case CXXMethod:
> case CXXConstructor:
> + case ConstructorUsingShadow:
> case CXXDestructor:
> case CXXConversion:
> case EnumConstant:
>
> Modified: cfe/trunk/lib/AST/DeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> DeclCXX.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/DeclCXX.cpp (original)
> +++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Jun 28 14:03:57 2016
> @@ -448,6 +448,15 @@ void CXXRecordDecl::addedMember(Decl *D)
> FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
> if (FunTmpl)
> D = FunTmpl->getTemplatedDecl();
> +
> + // FIXME: Pass NamedDecl* to addedMember?
> + Decl *DUnderlying = D;
> + if (auto *ND = dyn_cast<NamedDecl>(DUnderlying)) {
> + DUnderlying = ND->getUnderlyingDecl();
> + if (FunctionTemplateDecl *UnderlyingFunTmpl =
> + dyn_cast<FunctionTemplateDecl>(DUnderlying))
> + DUnderlying = UnderlyingFunTmpl->getTemplatedDecl();
> + }
>
> if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
> if (Method->isVirtual()) {
> @@ -503,15 +512,10 @@ void CXXRecordDecl::addedMember(Decl *D)
> data().PlainOldData = false;
> }
>
> - // Technically, "user-provided" is only defined for special member
> - // functions, but the intent of the standard is clearly that it
> should apply
> - // to all functions.
> - bool UserProvided = Constructor->isUserProvided();
> -
> if (Constructor->isDefaultConstructor()) {
> SMKind |= SMF_DefaultConstructor;
>
> - if (UserProvided)
> + if (Constructor->isUserProvided())
> data().UserProvidedDefaultConstructor = true;
> if (Constructor->isConstexpr())
> data().HasConstexprDefaultConstructor = true;
> @@ -529,9 +533,17 @@ void CXXRecordDecl::addedMember(Decl *D)
> } else if (Constructor->isMoveConstructor())
> SMKind |= SMF_MoveConstructor;
> }
> + }
>
> + // Handle constructors, including those inherited from base classes.
> + if (CXXConstructorDecl *Constructor =
> + dyn_cast<CXXConstructorDecl>(DUnderlying)) {
> // Record if we see any constexpr constructors which are neither copy
> // nor move constructors.
> + // C++1z [basic.types]p10:
> + // [...] has at least one constexpr constructor or constructor
> template
> + // (possibly inherited from a base class) that is not a copy or move
> + // constructor [...]
> if (Constructor->isConstexpr() && !Constructor->
> isCopyOrMoveConstructor())
> data().HasConstexprNonCopyMoveConstructor = true;
>
> @@ -541,8 +553,12 @@ void CXXRecordDecl::addedMember(Decl *D)
> // C++11 [dcl.init.aggr]p1:
> // An aggregate is an array or a class with no user-provided
> // constructors [...].
> + // C++11 [dcl.init.aggr]p1:
> + // An aggregate is an array or a class with no user-provided
> + // constructors (including those inherited from a base class) [...].
> if (getASTContext().getLangOpts().CPlusPlus11
> - ? UserProvided : !Constructor->isImplicit())
> + ? Constructor->isUserProvided()
> + : !Constructor->isImplicit())
> data().Aggregate = false;
> }
>
> @@ -1784,11 +1800,15 @@ SourceRange CXXCtorInitializer::getSourc
>
> void CXXConstructorDecl::anchor() { }
>
> -CXXConstructorDecl *
> -CXXConstructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
> - return new (C, ID) CXXConstructorDecl(C, nullptr, SourceLocation(),
> - DeclarationNameInfo(), QualType(),
> - nullptr, false, false, false,
> false);
> +CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
> + unsigned ID,
> + bool
> Inherited) {
> + unsigned Extra = additionalSizeToAlloc<InheritedConstructor>(
> Inherited);
> + auto *Result = new (C, ID, Extra) CXXConstructorDecl(
> + C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(),
> nullptr,
> + false, false, false, false, InheritedConstructor());
> + Result->IsInheritingConstructor = Inherited;
> + return Result;
> }
>
> CXXConstructorDecl *
> @@ -1797,13 +1817,16 @@ CXXConstructorDecl::Create(ASTContext &C
> const DeclarationNameInfo &NameInfo,
> QualType T, TypeSourceInfo *TInfo,
> bool isExplicit, bool isInline,
> - bool isImplicitlyDeclared, bool isConstexpr) {
> + bool isImplicitlyDeclared, bool isConstexpr,
> + InheritedConstructor Inherited) {
> assert(NameInfo.getName().getNameKind()
> == DeclarationName::CXXConstructorName &&
> "Name must refer to a constructor");
> - return new (C, RD) CXXConstructorDecl(C, RD, StartLoc, NameInfo, T,
> TInfo,
> - isExplicit, isInline,
> - isImplicitlyDeclared,
> isConstexpr);
> + unsigned Extra =
> + additionalSizeToAlloc<InheritedConstructor>(Inherited ? 1 : 0);
> + return new (C, RD, Extra) CXXConstructorDecl(
> + C, RD, StartLoc, NameInfo, T, TInfo, isExplicit, isInline,
> + isImplicitlyDeclared, isConstexpr, Inherited);
> }
>
> CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin()
> const {
> @@ -1918,23 +1941,6 @@ bool CXXConstructorDecl::isSpecializatio
> return true;
> }
>
> -const CXXConstructorDecl *CXXConstructorDecl::getInheritedConstructor()
> const {
> - // Hack: we store the inherited constructor in the overridden method
> table
> - method_iterator It = getASTContext().overridden_methods_begin(this);
> - if (It == getASTContext().overridden_methods_end(this))
> - return nullptr;
> -
> - return cast<CXXConstructorDecl>(*It);
> -}
> -
> -void
> -CXXConstructorDecl::setInheritedConstructor(const CXXConstructorDecl
> *BaseCtor){
> - // Hack: we store the inherited constructor in the overridden method
> table
> - assert(getASTContext().overridden_methods_size(this) == 0 &&
> - "Base ctor already set.");
> - getASTContext().addOverriddenMethod(this, BaseCtor);
> -}
> -
> void CXXDestructorDecl::anchor() { }
>
> CXXDestructorDecl *
> @@ -2130,10 +2136,24 @@ NamespaceAliasDecl::CreateDeserialized(A
>
> void UsingShadowDecl::anchor() { }
>
> +UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC,
> + SourceLocation Loc, UsingDecl *Using,
> + NamedDecl *Target)
> + : NamedDecl(K, DC, Loc, Using ? Using->getDeclName() :
> DeclarationName()),
> + redeclarable_base(C), Underlying(Target),
> + UsingOrNextShadow(cast<NamedDecl>(Using)) {
> + if (Target)
> + IdentifierNamespace = Target->getIdentifierNamespace();
> + setImplicit();
> +}
> +
> +UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, EmptyShell Empty)
> + : NamedDecl(K, nullptr, SourceLocation(), DeclarationName()),
> + redeclarable_base(C), Underlying(), UsingOrNextShadow() {}
> +
> UsingShadowDecl *
> UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
> - return new (C, ID) UsingShadowDecl(C, nullptr, SourceLocation(),
> - nullptr, nullptr);
> + return new (C, ID) UsingShadowDecl(UsingShadow, C, EmptyShell());
> }
>
> UsingDecl *UsingShadowDecl::getUsingDecl() const {
> @@ -2144,6 +2164,25 @@ UsingDecl *UsingShadowDecl::getUsingDecl
> return cast<UsingDecl>(Shadow->UsingOrNextShadow);
> }
>
> +void ConstructorUsingShadowDecl::anchor() { }
> +
> +ConstructorUsingShadowDecl *
> +ConstructorUsingShadowDecl::Create(ASTContext &C, DeclContext *DC,
> + SourceLocation Loc, UsingDecl *Using,
> + NamedDecl *Target, bool IsVirtual) {
> + return new (C, DC) ConstructorUsingShadowDecl(C, DC, Loc, Using, Target,
> + IsVirtual);
> +}
> +
> +ConstructorUsingShadowDecl *
> +ConstructorUsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned
> ID) {
> + return new (C, ID) ConstructorUsingShadowDecl(C, EmptyShell());
> +}
> +
> +CXXRecordDecl *ConstructorUsingShadowDecl::getNominatedBaseClass() const
> {
> + return getUsingDecl()->getQualifier()->getAsRecordDecl();
> +}
> +
> void UsingDecl::anchor() { }
>
> void UsingDecl::addShadowDecl(UsingShadowDecl *S) {
>
> Modified: cfe/trunk/lib/AST/Expr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> Expr.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/Expr.cpp (original)
> +++ cfe/trunk/lib/AST/Expr.cpp Tue Jun 28 14:03:57 2016
> @@ -3008,6 +3008,13 @@ bool Expr::HasSideEffects(const ASTConte
> break;
> }
>
> + case CXXInheritedCtorInitExprClass: {
> + const auto *ICIE = cast<CXXInheritedCtorInitExpr>(this);
> + if (!ICIE->getConstructor()->isTrivial() && IncludePossibleEffects)
> + return true;
> + break;
> + }
> +
> case LambdaExprClass: {
> const LambdaExpr *LE = cast<LambdaExpr>(this);
> for (LambdaExpr::capture_iterator I = LE->capture_begin(),
>
> Modified: cfe/trunk/lib/AST/ExprClassification.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> ExprClassification.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/ExprClassification.cpp (original)
> +++ cfe/trunk/lib/AST/ExprClassification.cpp Tue Jun 28 14:03:57 2016
> @@ -360,6 +360,7 @@ static Cl::Kinds ClassifyInternal(ASTCon
>
> // Some C++ expressions are always class temporaries.
> case Expr::CXXConstructExprClass:
> + case Expr::CXXInheritedCtorInitExprClass:
> case Expr::CXXTemporaryObjectExprClass:
> case Expr::LambdaExprClass:
> case Expr::CXXStdInitializerListExprClass:
>
> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> ExprConstant.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> +++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Jun 28 14:03:57 2016
> @@ -997,6 +997,16 @@ void EvalInfo::addCallStack(unsigned Lim
> continue;
> }
>
> + // Use a different note for an inheriting constructor, because from
> the
> + // user's perspective it's not really a function at all.
> + if (auto *CD = dyn_cast_or_null<CXXConstructorDecl>(Frame->Callee)) {
> + if (CD->isInheritingConstructor()) {
> + addDiag(Frame->CallLoc, diag::note_constexpr_
> inherited_ctor_call_here)
> + << CD->getParent();
> + continue;
> + }
> + }
> +
> SmallVector<char, 128> Buffer;
> llvm::raw_svector_ostream Out(Buffer);
> describeCall(Frame, Out);
> @@ -3845,11 +3855,25 @@ static bool CheckConstexprFunction(EvalI
>
> if (Info.getLangOpts().CPlusPlus11) {
> const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;
> - // FIXME: If DiagDecl is an implicitly-declared special member
> function, we
> - // should be much more explicit about why it's not constexpr.
> - Info.Diag(CallLoc, diag::note_constexpr_invalid_function, 1)
> - << DiagDecl->isConstexpr() << isa<CXXConstructorDecl>(DiagDecl)
> - << DiagDecl;
> +
> + // If this function is not constexpr because it is an inherited
> + // non-constexpr constructor, diagnose that directly.
> + auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
> + if (CD && CD->isInheritingConstructor()) {
> + auto *Inherited = CD->getInheritedConstructor().getConstructor();
> + if (!Inherited->isConstexpr())
> + DiagDecl = CD = Inherited;
> + }
> +
> + // FIXME: If DiagDecl is an implicitly-declared special member
> function
> + // or an inheriting constructor, we should be much more explicit
> about why
> + // it's not constexpr.
> + if (CD && CD->isInheritingConstructor())
> + Info.Diag(CallLoc, diag::note_constexpr_invalid_inhctor, 1)
> + << CD->getInheritedConstructor().getConstructor()->getParent();
> + else
> + Info.Diag(CallLoc, diag::note_constexpr_invalid_function, 1)
> + << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
> Info.Note(DiagDecl->getLocation(), diag::note_declared_at);
> } else {
> Info.Diag(CallLoc, diag::note_invalid_subexpr_in_const_expr);
> @@ -3945,14 +3969,11 @@ static bool HandleFunctionCall(SourceLoc
> }
>
> /// Evaluate a constructor call.
> -static bool HandleConstructorCall(SourceLocation CallLoc, const LValue
> &This,
> - ArrayRef<const Expr*> Args,
> +static bool HandleConstructorCall(const Expr *E, const LValue &This,
> + APValue *ArgValues,
> const CXXConstructorDecl *Definition,
> EvalInfo &Info, APValue &Result) {
> - ArgVector ArgValues(Args.size());
> - if (!EvaluateArgs(Args, ArgValues, Info))
> - return false;
> -
> + SourceLocation CallLoc = E->getExprLoc();
> if (!Info.CheckCallLimit(CallLoc))
> return false;
>
> @@ -3962,14 +3983,14 @@ static bool HandleConstructorCall(Source
> return false;
> }
>
> - CallStackFrame Frame(Info, CallLoc, Definition, &This,
> ArgValues.data());
> + CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues);
>
> // FIXME: Creating an APValue just to hold a nonexistent return value is
> // wasteful.
> APValue RetVal;
> StmtResult Ret = {RetVal, nullptr};
>
> - // If it's a delegating constructor, just delegate.
> + // If it's a delegating constructor, delegate.
> if (Definition->isDelegatingConstructor()) {
> CXXConstructorDecl::init_const_iterator I = Definition->init_begin();
> {
> @@ -3993,8 +4014,9 @@ static bool HandleConstructorCall(Source
> (Definition->isTrivial() && hasFields(Definition->getParent()))))
> {
> LValue RHS;
> RHS.setFrom(Info.Ctx, ArgValues[0]);
> - return handleLValueToRValueConversion(Info, Args[0],
> Args[0]->getType(),
> - RHS, Result);
> + return handleLValueToRValueConversion(
> + Info, E, Definition->getParamDecl(0)->
> getType().getNonReferenceType(),
> + RHS, Result);
> }
>
> // Reserve space for the struct members.
> @@ -4088,6 +4110,18 @@ static bool HandleConstructorCall(Source
> EvaluateStmt(Ret, Info, Definition->getBody()) != ESR_Failed;
> }
>
> +static bool HandleConstructorCall(const Expr *E, const LValue &This,
> + ArrayRef<const Expr*> Args,
> + const CXXConstructorDecl *Definition,
> + EvalInfo &Info, APValue &Result) {
> + ArgVector ArgValues(Args.size());
> + if (!EvaluateArgs(Args, ArgValues, Info))
> + return false;
> +
> + return HandleConstructorCall(E, This, ArgValues.data(), Definition,
> + Info, Result);
> +}
> +
> //===-------------------------------------------------------
> ---------------===//
> // Generic Evaluation
> //===-------------------------------------------------------
> ---------------===//
> @@ -5380,6 +5414,7 @@ namespace {
> bool VisitCXXConstructExpr(const CXXConstructExpr *E) {
> return VisitCXXConstructExpr(E, E->getType());
> }
> + bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr
> *E);
> bool VisitCXXConstructExpr(const CXXConstructExpr *E, QualType T);
> bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr
> *E);
> };
> @@ -5631,7 +5666,29 @@ bool RecordExprEvaluator::VisitCXXConstr
> return false;
>
> auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs());
> - return HandleConstructorCall(E->getExprLoc(), This, Args,
> + return HandleConstructorCall(E, This, Args,
> + cast<CXXConstructorDecl>(Definition),
> Info,
> + Result);
> +}
> +
> +bool RecordExprEvaluator::VisitCXXInheritedCtorInitExpr(
> + const CXXInheritedCtorInitExpr *E) {
> + if (!Info.CurrentCall) {
> + assert(Info.checkingPotentialConstantExpression());
> + return false;
> + }
> +
> + const CXXConstructorDecl *FD = E->getConstructor();
> + if (FD->isInvalidDecl() || FD->getParent()->isInvalidDecl())
> + return false;
> +
> + const FunctionDecl *Definition = nullptr;
> + auto Body = FD->getBody(Definition);
> +
> + if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition,
> Body))
> + return false;
> +
> + return HandleConstructorCall(E, This, Info.CurrentCall->Arguments,
> cast<CXXConstructorDecl>(Definition),
> Info,
> Result);
> }
> @@ -9305,6 +9362,7 @@ static ICEDiag CheckICE(const Expr* E, c
> case Expr::TypoExprClass:
> case Expr::DependentScopeDeclRefExprClass:
> case Expr::CXXConstructExprClass:
> + case Expr::CXXInheritedCtorInitExprClass:
> case Expr::CXXStdInitializerListExprClass:
> case Expr::CXXBindTemporaryExprClass:
> case Expr::ExprWithCleanupsClass:
> @@ -9768,17 +9826,17 @@ bool Expr::isPotentialConstantExpr(const
>
> ArrayRef<const Expr*> Args;
>
> - SourceLocation Loc = FD->getLocation();
> -
> APValue Scratch;
> if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
> // Evaluate the call as a constant initializer, to allow the
> construction
> // of objects of non-literal types.
> Info.setEvaluatingDecl(This.getLValueBase(), Scratch);
> - HandleConstructorCall(Loc, This, Args, CD, Info, Scratch);
> - } else
> + HandleConstructorCall(&VIE, This, Args, CD, Info, Scratch);
> + } else {
> + SourceLocation Loc = FD->getLocation();
> HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This :
> nullptr,
> Args, FD->getBody(), Info, Scratch, nullptr);
> + }
>
> return Diags.empty();
> }
>
> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> ItaniumMangle.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue Jun 28 14:03:57 2016
> @@ -397,7 +397,7 @@ private:
> void mangleCastExpression(const Expr *E, StringRef CastEncoding);
> void mangleInitListElements(const InitListExpr *InitList);
> void mangleExpression(const Expr *E, unsigned Arity = UnknownArity);
> - void mangleCXXCtorType(CXXCtorType T);
> + void mangleCXXCtorType(CXXCtorType T, const CXXRecordDecl
> *InheritedFrom);
> void mangleCXXDtorType(CXXDtorType T);
>
> void mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs,
> @@ -502,6 +502,12 @@ void CXXNameMangler::mangleFunctionEncod
> FunctionTypeDepth.pop(Saved);
> }
>
> + // When mangling an inheriting constructor, the bare function type used
> is
> + // that of the inherited constructor.
> + if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
> + if (auto Inherited = CD->getInheritedConstructor())
> + FD = Inherited.getConstructor();
> +
> // Whether the mangling of a function type includes the return type
> depends on
> // the context and the nature of the function. The rules for deciding
> whether
> // the return type is included are:
> @@ -562,7 +568,7 @@ static bool isStdNamespace(const DeclCon
> static const TemplateDecl *
> isTemplate(const NamedDecl *ND, const TemplateArgumentList
> *&TemplateArgs) {
> // Check if we have a function template.
> - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){
> + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
> if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {
> TemplateArgs = FD->getTemplateSpecializationArgs();
> return TD;
> @@ -1048,16 +1054,31 @@ void CXXNameMangler::mangleUnqualifiedNa
> case DeclarationName::ObjCMultiArgSelector:
> llvm_unreachable("Can't mangle Objective-C selector names here!");
>
> - case DeclarationName::CXXConstructorName:
> + case DeclarationName::CXXConstructorName: {
> + const CXXRecordDecl *InheritedFrom = nullptr;
> + const TemplateArgumentList *InheritedTemplateArgs = nullptr;
> + if (auto Inherited =
> + cast<CXXConstructorDecl>(ND)->getInheritedConstructor()) {
> + InheritedFrom = Inherited.getConstructor()->getParent();
> + InheritedTemplateArgs =
> + Inherited.getConstructor()->getTemplateSpecializationArgs();
> + }
> +
> if (ND == Structor)
> // If the named decl is the C++ constructor we're mangling, use the
> type
> // we were given.
> - mangleCXXCtorType(static_cast<CXXCtorType>(StructorType));
> + mangleCXXCtorType(static_cast<CXXCtorType>(StructorType),
> InheritedFrom);
> else
> // Otherwise, use the complete constructor name. This is relevant
> if a
> // class with a constructor is declared within a constructor.
> - mangleCXXCtorType(Ctor_Complete);
> + mangleCXXCtorType(Ctor_Complete, InheritedFrom);
> +
> + // FIXME: The template arguments are part of the enclosing prefix or
> + // nested-name, but it's more convenient to mangle them here.
> + if (InheritedTemplateArgs)
> + mangleTemplateArgs(*InheritedTemplateArgs);
> break;
> + }
>
> case DeclarationName::CXXDestructorName:
> if (ND == Structor)
> @@ -2909,6 +2930,7 @@ recurse:
> case Expr::MSPropertySubscriptExprClass:
> case Expr::TypoExprClass: // This should no longer exist in the AST by
> now.
> case Expr::OMPArraySectionExprClass:
> + case Expr::CXXInheritedCtorInitExprClass:
> llvm_unreachable("unexpected statement kind");
>
> // FIXME: invent manglings for all these.
> @@ -3688,25 +3710,33 @@ void CXXNameMangler::mangleFunctionParam
> Out << '_';
> }
>
> -void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
> +void CXXNameMangler::mangleCXXCtorType(CXXCtorType T,
> + const CXXRecordDecl
> *InheritedFrom) {
> // <ctor-dtor-name> ::= C1 # complete object constructor
> // ::= C2 # base object constructor
> + // ::= CI1 <type> # complete inheriting constructor
> + // ::= CI2 <type> # base inheriting constructor
> //
> // In addition, C5 is a comdat name with C1 and C2 in it.
> + Out << 'C';
> + if (InheritedFrom)
> + Out << 'I';
> switch (T) {
> case Ctor_Complete:
> - Out << "C1";
> + Out << '1';
> break;
> case Ctor_Base:
> - Out << "C2";
> + Out << '2';
> break;
> case Ctor_Comdat:
> - Out << "C5";
> + Out << '5';
> break;
> case Ctor_DefaultClosure:
> case Ctor_CopyingClosure:
> llvm_unreachable("closure constructors don't exist for the Itanium
> ABI!");
> }
> + if (InheritedFrom)
> + mangleName(InheritedFrom);
> }
>
> void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
>
> Modified: cfe/trunk/lib/AST/NestedNameSpecifier.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> NestedNameSpecifier.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/NestedNameSpecifier.cpp (original)
> +++ cfe/trunk/lib/AST/NestedNameSpecifier.cpp Tue Jun 28 14:03:57 2016
> @@ -171,10 +171,19 @@ NamespaceAliasDecl *NestedNameSpecifier:
>
> /// \brief Retrieve the record declaration stored in this nested name
> specifier.
> CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
> - if (Prefix.getInt() == StoredDecl)
> + switch (Prefix.getInt()) {
> + case StoredIdentifier:
> + return nullptr;
> +
> + case StoredDecl:
> return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier));
>
> - return nullptr;
> + case StoredTypeSpec:
> + case StoredTypeSpecWithTemplate:
> + return getAsType()->getAsCXXRecordDecl();
> + }
> +
> + llvm_unreachable("Invalid NNS Kind!");
> }
>
> /// \brief Whether this nested name specifier refers to a dependent
>
> Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> StmtPrinter.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
> +++ cfe/trunk/lib/AST/StmtPrinter.cpp Tue Jun 28 14:03:57 2016
> @@ -2188,6 +2188,11 @@ void StmtPrinter::VisitCXXConstructExpr(
> OS << "}";
> }
>
> +void StmtPrinter::VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr
> *E) {
> + // Parens are printed by the surrounding context.
> + OS << "<forwarded>";
> +}
> +
> void StmtPrinter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr
> *E) {
> PrintExpr(E->getSubExpr());
> }
>
> Modified: cfe/trunk/lib/AST/StmtProfile.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> StmtProfile.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/StmtProfile.cpp (original)
> +++ cfe/trunk/lib/AST/StmtProfile.cpp Tue Jun 28 14:03:57 2016
> @@ -1287,6 +1287,12 @@ void StmtProfiler::VisitCXXConstructExpr
> ID.AddBoolean(S->isElidable());
> }
>
> +void StmtProfiler::VisitCXXInheritedCtorInitExpr(
> + const CXXInheritedCtorInitExpr *S) {
> + VisitExpr(S);
> + VisitDecl(S->getConstructor());
> +}
> +
> void StmtProfiler::VisitCXXFunctionalCastExpr(const
> CXXFunctionalCastExpr *S) {
> VisitExplicitCastExpr(S);
> }
>
> Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
> CGCall.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGCall.cpp Tue Jun 28 14:03:57 2016
> @@ -244,6 +244,15 @@ CodeGenTypes::arrangeCXXMethodDeclaratio
> return arrangeFreeFunctionType(prototype, MD);
> }
>
> +bool CodeGenTypes::inheritingCtorHasParams(
> + const InheritedConstructor &Inherited, CXXCtorType Type) {
> + // Parameters are unnecessary if we're constructing a base class
> subobject
> + // and the inherited constructor lives in a virtual base.
> + return Type == Ctor_Complete ||
> + !Inherited.getShadowDecl()->constructsVirtualBase() ||
> + !Target.getCXXABI().hasConstructorVariants();
> + }
> +
> const CGFunctionInfo &
> CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,
> StructorType Type) {
> @@ -252,9 +261,16 @@ CodeGenTypes::arrangeCXXStructorDeclarat
> SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos;
> argTypes.push_back(GetThisType(Context, MD->getParent()));
>
> + bool PassParams = true;
> +
> GlobalDecl GD;
> if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
> GD = GlobalDecl(CD, toCXXCtorType(Type));
> +
> + // A base class inheriting constructor doesn't get forwarded arguments
> + // needed to construct a virtual base (or base class thereof).
> + if (auto Inherited = CD->getInheritedConstructor())
> + PassParams = inheritingCtorHasParams(Inherited,
> toCXXCtorType(Type));
> } else {
> auto *DD = dyn_cast<CXXDestructorDecl>(MD);
> GD = GlobalDecl(DD, toCXXDtorType(Type));
> @@ -263,12 +279,14 @@ CodeGenTypes::arrangeCXXStructorDeclarat
> CanQual<FunctionProtoType> FTP = GetFormalType(MD);
>
> // Add the formal parameters.
> - appendParameterTypes(*this, argTypes, paramInfos, FTP, MD);
> + if (PassParams)
> + appendParameterTypes(*this, argTypes, paramInfos, FTP, MD);
>
> TheCXXABI.buildStructorSignature(MD, Type, argTypes);
>
> RequiredArgs required =
> - (MD->isVariadic() ? RequiredArgs(argTypes.size()) :
> RequiredArgs::All);
> + (PassParams && MD->isVariadic() ? RequiredArgs(argTypes.size())
> + : RequiredArgs::All);
>
> FunctionType::ExtInfo extInfo = FTP->getExtInfo();
> CanQualType resultType = TheCXXABI.HasThisReturn(GD)
> @@ -3186,10 +3204,10 @@ void CodeGenFunction::EmitCallArgs(
> size_t CallArgsStart = Args.size();
> for (int I = ArgTypes.size() - 1; I >= 0; --I) {
> CallExpr::const_arg_iterator Arg = ArgRange.begin() + I;
> + MaybeEmitImplicitObjectSize(I, *Arg);
> EmitCallArg(Args, *Arg, ArgTypes[I]);
> EmitNonNullArgCheck(Args.back().RV, ArgTypes[I],
> (*Arg)->getExprLoc(),
> CalleeDecl, ParamsToSkip + I);
> - MaybeEmitImplicitObjectSize(I, *Arg);
> }
>
> // Un-reverse the arguments we just evaluated so they match up with
> the LLVM
>
> Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
> CGClass.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGClass.cpp Tue Jun 28 14:03:57 2016
> @@ -2048,6 +2048,62 @@ void CodeGenFunction::EmitCXXConstructor
> bool ForVirtualBase,
> bool Delegating, Address
> This,
> const CXXConstructExpr *E) {
> + CallArgList Args;
> +
> + // Push the this ptr.
> + Args.add(RValue::get(This.getPointer()), D->getThisType(getContext()));
> +
> + // If this is a trivial constructor, emit a memcpy now before we lose
> + // the alignment information on the argument.
> + // FIXME: It would be better to preserve alignment information into
> CallArg.
> + if (isMemcpyEquivalentSpecialMember(D)) {
> + assert(E->getNumArgs() == 1 && "unexpected argcount for trivial
> ctor");
> +
> + const Expr *Arg = E->getArg(0);
> + QualType SrcTy = Arg->getType();
> + Address Src = EmitLValue(Arg).getAddress();
> + QualType DestTy = getContext().getTypeDeclType(D->getParent());
> + EmitAggregateCopyCtor(This, Src, DestTy, SrcTy);
> + return;
> + }
> +
> + // Add the rest of the user-supplied arguments.
> + const FunctionProtoType *FPT = D->getType()->castAs<
> FunctionProtoType>();
> + EmitCallArgs(Args, FPT, E->arguments(), E->getConstructor());
> +
> + EmitCXXConstructorCall(D, Type, ForVirtualBase, Delegating, This, Args);
> +}
> +
> +static bool canEmitDelegateCallArgs(CodeGenFunction &CGF,
> + const CXXConstructorDecl *Ctor,
> + CXXCtorType Type, CallArgList &Args) {
> + // We can't forward a variadic call.
> + if (Ctor->isVariadic())
> + return false;
> +
> + if (CGF.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee())
> {
> + // If the parameters are callee-cleanup, it's not safe to forward.
> + for (auto *P : Ctor->parameters())
> + if (P->getType().isDestructedType())
> + return false;
> +
> + // Likewise if they're inalloca.
> + const CGFunctionInfo &Info =
> + CGF.CGM.getTypes().arrangeCXXConstructorCall(Args, Ctor, Type,
> 0);
> + if (Info.usesInAlloca())
> + return false;
> + }
> +
> + // Anything else should be OK.
> + return true;
> +}
> +
> +void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
> + CXXCtorType Type,
> + bool ForVirtualBase,
> + bool Delegating,
> + Address This,
> + CallArgList &Args) {
> const CXXRecordDecl *ClassDecl = D->getParent();
>
> // C++11 [class.mfct.non-static]p2:
> @@ -2058,7 +2114,7 @@ void CodeGenFunction::EmitCXXConstructor
> This.getPointer(), getContext().getRecordType(
> ClassDecl));
>
> if (D->isTrivial() && D->isDefaultConstructor()) {
> - assert(E->getNumArgs() == 0 && "trivial default ctor with args");
> + assert(Args.size() == 1 && "trivial default ctor with args");
> return;
> }
>
> @@ -2066,24 +2122,24 @@ void CodeGenFunction::EmitCXXConstructor
> // union copy constructor, we must emit a memcpy, because the AST does
> not
> // model that copy.
> if (isMemcpyEquivalentSpecialMember(D)) {
> - assert(E->getNumArgs() == 1 && "unexpected argcount for trivial
> ctor");
> + assert(Args.size() == 2 && "unexpected argcount for trivial ctor");
>
> - const Expr *Arg = E->getArg(0);
> - QualType SrcTy = Arg->getType();
> - Address Src = EmitLValue(Arg).getAddress();
> + QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType();
> + Address Src(Args[1].RV.getScalarVal(), getNaturalTypeAlignment(SrcTy)
> );
> QualType DestTy = getContext().getTypeDeclType(ClassDecl);
> EmitAggregateCopyCtor(This, Src, DestTy, SrcTy);
> return;
> }
>
> - CallArgList Args;
> -
> - // Push the this ptr.
> - Args.add(RValue::get(This.getPointer()), D->getThisType(getContext()));
> -
> - // Add the rest of the user-supplied arguments.
> - const FunctionProtoType *FPT = D->getType()->castAs<
> FunctionProtoType>();
> - EmitCallArgs(Args, FPT, E->arguments(), E->getConstructor());
> + // Check whether we can actually emit the constructor before trying to
> do so.
> + if (auto Inherited = D->getInheritedConstructor()) {
> + if (getTypes().inheritingCtorHasParams(Inherited, Type) &&
> + !canEmitDelegateCallArgs(*this, D, Type, Args)) {
> + EmitInlinedInheritingCXXConstructorCall(D, Type, ForVirtualBase,
> + Delegating, Args);
> + return;
> + }
> + }
>
> // Insert any ABI-specific implicit constructor arguments.
> unsigned ExtraArgs = CGM.getCXXABI().addImplicitConstructorArgs(
> @@ -2113,6 +2169,95 @@ void CodeGenFunction::EmitCXXConstructor
> EmitVTableAssumptionLoads(ClassDecl, This);
> }
>
> +void CodeGenFunction::EmitInheritedCXXConstructorCall(
> + const CXXConstructorDecl *D, bool ForVirtualBase, Address This,
> + bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E) {
> + CallArgList Args;
> + CallArg ThisArg(RValue::get(This.getPointer()),
> D->getThisType(getContext()),
> + /*NeedsCopy=*/false);
> +
> + // Forward the parameters.
> + if (InheritedFromVBase &&
> + CGM.getTarget().getCXXABI().hasConstructorVariants()) {
> + // Nothing to do; this construction is not responsible for
> constructing
> + // the base class containing the inherited constructor.
> + // FIXME: Can we just pass undef's for the remaining arguments if we
> don't
> + // have constructor variants?
> + Args.push_back(ThisArg);
> + } else if (!CXXInheritedCtorInitExprArgs.empty()) {
> + // The inheriting constructor was inlined; just inject its arguments.
> + assert(CXXInheritedCtorInitExprArgs.size() >= D->getNumParams() &&
> + "wrong number of parameters for inherited constructor call");
> + Args = CXXInheritedCtorInitExprArgs;
> + Args[0] = ThisArg;
> + } else {
> + // The inheriting constructor was not inlined. Emit delegating
> arguments.
> + Args.push_back(ThisArg);
> + const auto *OuterCtor = cast<CXXConstructorDecl>(CurCodeDecl);
> + assert(OuterCtor->getNumParams() == D->getNumParams());
> + assert(!OuterCtor->isVariadic() && "should have been inlined");
> +
> + for (const auto *Param : OuterCtor->parameters()) {
> + assert(getContext().hasSameUnqualifiedType(
> + OuterCtor->getParamDecl(Param->getFunctionScopeIndex())->
> getType(),
> + Param->getType()));
> + EmitDelegateCallArg(Args, Param, E->getLocation());
> +
> + // Forward __attribute__(pass_object_size).
> + if (Param->hasAttr<PassObjectSizeAttr>()) {
> + auto *POSParam = SizeArguments[Param];
> + assert(POSParam && "missing pass_object_size value for
> forwarding");
> + EmitDelegateCallArg(Args, POSParam, E->getLocation());
> + }
> + }
> + }
> +
> + EmitCXXConstructorCall(D, Ctor_Base, ForVirtualBase,
> /*Delegating*/false,
> + This, Args);
> +}
> +
> +void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall(
> + const CXXConstructorDecl *Ctor, CXXCtorType CtorType, bool
> ForVirtualBase,
> + bool Delegating, CallArgList &Args) {
> + InlinedInheritingConstructorScope Scope(*this, GlobalDecl(Ctor,
> CtorType));
> +
> + // Save the arguments to be passed to the inherited constructor.
> + CXXInheritedCtorInitExprArgs = Args;
> +
> + FunctionArgList Params;
> + QualType RetType = BuildFunctionArgList(CurGD, Params);
> + FnRetTy = RetType;
> +
> + // Insert any ABI-specific implicit constructor arguments.
> + CGM.getCXXABI().addImplicitConstructorArgs(*this, Ctor, CtorType,
> + ForVirtualBase, Delegating,
> Args);
> +
> + // Emit a simplified prolog. We only need to emit the implicit params.
> + assert(Args.size() >= Params.size() && "too few arguments for call");
> + for (unsigned I = 0, N = Args.size(); I != N; ++I) {
> + if (I < Params.size() && isa<ImplicitParamDecl>(Params[I])) {
> + const RValue &RV = Args[I].RV;
> + assert(!RV.isComplex() && "complex indirect params not supported");
> + ParamValue Val = RV.isScalar()
> + ? ParamValue::forDirect(RV.getScalarVal())
> + : ParamValue::forIndirect(RV.
> getAggregateAddress());
> + EmitParmDecl(*Params[I], Val, I + 1);
> + }
> + }
> +
> + // Create a return value slot if the ABI implementation wants one.
> + // FIXME: This is dumb, we should ask the ABI not to try to set the
> return
> + // value instead.
> + if (!RetType->isVoidType())
> + ReturnValue = CreateIRTemp(RetType, "retval.inhctor");
> +
> + CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
> + CXXThisValue = CXXABIThisValue;
> +
> + // Directly emit the constructor initializers.
> + EmitCtorPrologue(Ctor, CtorType, Params);
> +}
> +
> void CodeGenFunction::EmitVTableAssumptionLoad(const VPtr &Vptr, Address
> This) {
> llvm::Value *VTableGlobal =
> CGM.getCXXABI().getVTableAddressPoint(Vptr.Base, Vptr.VTableClass);
> @@ -2145,19 +2290,6 @@ void
> CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl
> *D,
> Address This, Address Src,
> const CXXConstructExpr
> *E) {
> - if (isMemcpyEquivalentSpecialMember(D)) {
> - assert(E->getNumArgs() == 1 && "unexpected argcount for trivial
> ctor");
> - assert(D->isCopyOrMoveConstructor() &&
> - "trivial 1-arg ctor not a copy/move ctor");
> - EmitAggregateCopyCtor(This, Src,
> - getContext().getTypeDeclType(D->getParent()),
> - (*E->arg_begin())->getType());
> - return;
> - }
> - llvm::Value *Callee = CGM.getAddrOfCXXStructor(D,
> StructorType::Complete);
> - assert(D->isInstance() &&
> - "Trying to emit a member call expr on a static method!");
> -
> const FunctionProtoType *FPT = D->getType()->castAs<
> FunctionProtoType>();
>
> CallArgList Args;
> @@ -2175,8 +2307,7 @@ CodeGenFunction::EmitSynthesizedCXXCopyC
> EmitCallArgs(Args, FPT, drop_begin(E->arguments(), 1),
> E->getConstructor(),
> /*ParamsToSkip*/ 1);
>
> - EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT,
> RequiredArgs::All),
> - Callee, ReturnValueSlot(), Args, D);
> + EmitCXXConstructorCall(D, Ctor_Complete, false, false, This, Args);
> }
>
> void
> @@ -2190,21 +2321,17 @@ CodeGenFunction::EmitDelegateCXXConstruc
> assert(I != E && "no parameters to constructor");
>
> // this
> - DelegateArgs.add(RValue::get(LoadCXXThis()), (*I)->getType());
> + Address This = LoadCXXThisAddress();
> + DelegateArgs.add(RValue::get(This.getPointer()), (*I)->getType());
> ++I;
>
> - // vtt
> - if (llvm::Value *VTT = GetVTTParameter(GlobalDecl(Ctor, CtorType),
> - /*ForVirtualBase=*/false,
> - /*Delegating=*/true)) {
> - QualType VoidPP = getContext().getPointerType(
> getContext().VoidPtrTy);
> - DelegateArgs.add(RValue::get(VTT), VoidPP);
> -
> - if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) {
> - assert(I != E && "cannot skip vtt parameter, already done with
> args");
> - assert((*I)->getType() == VoidPP && "skipping parameter not of vtt
> type");
> - ++I;
> - }
> + // FIXME: The location of the VTT parameter in the parameter list is
> + // specific to the Itanium ABI and shouldn't be hardcoded here.
> + if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) {
> + assert(I != E && "cannot skip vtt parameter, already done with args");
> + assert((*I)->getType()->isPointerType() &&
> + "skipping parameter not of vtt type");
> + ++I;
> }
>
> // Explicit arguments.
> @@ -2214,11 +2341,8 @@ CodeGenFunction::EmitDelegateCXXConstruc
> EmitDelegateCallArg(DelegateArgs, param, Loc);
> }
>
> - llvm::Value *Callee =
> - CGM.getAddrOfCXXStructor(Ctor, getFromCtorType(CtorType));
> - EmitCall(CGM.getTypes()
> - .arrangeCXXStructorDeclaration(Ctor,
> getFromCtorType(CtorType)),
> - Callee, ReturnValueSlot(), DelegateArgs, Ctor);
> + EmitCXXConstructorCall(Ctor, CtorType, /*ForVirtualBase=*/false,
> + /*Delegating=*/true, This, DelegateArgs);
> }
>
> namespace {
>
> Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
> CGDecl.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Tue Jun 28 14:03:57 2016
> @@ -85,6 +85,7 @@ void CodeGenFunction::EmitDecl(const Dec
> case Decl::Captured:
> case Decl::ClassScopeFunctionSpecialization:
> case Decl::UsingShadow:
> + case Decl::ConstructorUsingShadow:
> case Decl::ObjCTypeParam:
> llvm_unreachable("Declaration should not be in declstmts!");
> case Decl::Function: // void X();
>
> Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
> CGExprAgg.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Tue Jun 28 14:03:57 2016
> @@ -175,6 +175,7 @@ public:
> }
> void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
> void VisitCXXConstructExpr(const CXXConstructExpr *E);
> + void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E);
> void VisitLambdaExpr(LambdaExpr *E);
> void VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E);
> void VisitExprWithCleanups(ExprWithCleanups *E);
> @@ -998,6 +999,14 @@ AggExprEmitter::VisitCXXConstructExpr(co
> CGF.EmitCXXConstructExpr(E, Slot);
> }
>
> +void AggExprEmitter::VisitCXXInheritedCtorInitExpr(
> + const CXXInheritedCtorInitExpr *E) {
> + AggValueSlot Slot = EnsureSlot(E->getType());
> + CGF.EmitInheritedCXXConstructorCall(
> + E->getConstructor(), E->constructsVBase(), Slot.getAddress(),
> + E->inheritedFromVBase(), E);
> +}
> +
> void
> AggExprEmitter::VisitLambdaExpr(LambdaExpr *E) {
> AggValueSlot Slot = EnsureSlot(E->getType());
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
> CodeGenFunction.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Tue Jun 28 14:03:57 2016
> @@ -928,18 +928,11 @@ static void TryMarkNoThrow(llvm::Functio
> F->setDoesNotThrow();
> }
>
> -void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
> - const CGFunctionInfo &FnInfo) {
> +QualType CodeGenFunction::BuildFunctionArgList(GlobalDecl GD,
> + FunctionArgList &Args) {
> const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
> -
> - // Check if we should generate debug info for this function.
> - if (FD->hasAttr<NoDebugAttr>())
> - DebugInfo = nullptr; // disable debug info indefinitely for this
> function
> -
> - FunctionArgList Args;
> QualType ResTy = FD->getReturnType();
>
> - CurGD = GD;
> const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
> if (MD && MD->isInstance()) {
> if (CGM.getCXXABI().HasThisReturn(GD))
> @@ -949,22 +942,48 @@ void CodeGenFunction::GenerateCode(Globa
> CGM.getCXXABI().buildThisParam(*this, Args);
> }
>
> - for (auto *Param : FD->parameters()) {
> - Args.push_back(Param);
> - if (!Param->hasAttr<PassObjectSizeAttr>())
> - continue;
> -
> - IdentifierInfo *NoID = nullptr;
> - auto *Implicit = ImplicitParamDecl::Create(
> - getContext(), Param->getDeclContext(), Param->getLocation(), NoID,
> - getContext().getSizeType());
> - SizeArguments[Param] = Implicit;
> - Args.push_back(Implicit);
> + // The base version of an inheriting constructor whose constructed base
> is a
> + // virtual base is not passed any arguments (because it doesn't
> actually call
> + // the inherited constructor).
> + bool PassedParams = true;
> + if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD))
> + if (auto Inherited = CD->getInheritedConstructor())
> + PassedParams =
> + getTypes().inheritingCtorHasParams(Inherited,
> GD.getCtorType());
> +
> + if (PassedParams) {
> + for (auto *Param : FD->parameters()) {
> + Args.push_back(Param);
> + if (!Param->hasAttr<PassObjectSizeAttr>())
> + continue;
> +
> + IdentifierInfo *NoID = nullptr;
> + auto *Implicit = ImplicitParamDecl::Create(
> + getContext(), Param->getDeclContext(), Param->getLocation(),
> NoID,
> + getContext().getSizeType());
> + SizeArguments[Param] = Implicit;
> + Args.push_back(Implicit);
> + }
> }
>
> if (MD && (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)))
> CGM.getCXXABI().addImplicitStructorParams(*this, ResTy, Args);
>
> + return ResTy;
> +}
> +
> +void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
> + const CGFunctionInfo &FnInfo) {
> + const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
> + CurGD = GD;
> +
> + FunctionArgList Args;
> + QualType ResTy = BuildFunctionArgList(GD, Args);
> +
> + // Check if we should generate debug info for this function.
> + if (FD->hasAttr<NoDebugAttr>())
> + DebugInfo = nullptr; // disable debug info indefinitely for this
> function
> +
> SourceRange BodyRange;
> if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange();
> CurEHLocation = BodyRange.getEnd();
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
> CodeGenFunction.h?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Jun 28 14:03:57 2016
> @@ -1065,6 +1065,61 @@ public:
> CharUnits OldCXXThisAlignment;
> };
>
> + class InlinedInheritingConstructorScope {
> + public:
> + InlinedInheritingConstructorScope(CodeGenFunction &CGF, GlobalDecl
> GD)
> + : CGF(CGF), OldCurGD(CGF.CurGD), OldCurFuncDecl(CGF.CurFuncDecl),
> + OldCurCodeDecl(CGF.CurCodeDecl),
> + OldCXXABIThisDecl(CGF.CXXABIThisDecl),
> + OldCXXABIThisValue(CGF.CXXABIThisValue),
> + OldCXXThisValue(CGF.CXXThisValue),
> + OldCXXABIThisAlignment(CGF.CXXABIThisAlignment),
> + OldCXXThisAlignment(CGF.CXXThisAlignment),
> + OldReturnValue(CGF.ReturnValue), OldFnRetTy(CGF.FnRetTy),
> + OldCXXInheritedCtorInitExprArgs(
> + std::move(CGF.CXXInheritedCtorInitExprArgs)) {
> + CGF.CurGD = GD;
> + CGF.CurFuncDecl = CGF.CurCodeDecl =
> + cast<CXXConstructorDecl>(GD.getDecl());
> + CGF.CXXABIThisDecl = nullptr;
> + CGF.CXXABIThisValue = nullptr;
> + CGF.CXXThisValue = nullptr;
> + CGF.CXXABIThisAlignment = CharUnits();
> + CGF.CXXThisAlignment = CharUnits();
> + CGF.ReturnValue = Address::invalid();
> + CGF.FnRetTy = QualType();
> + CGF.CXXInheritedCtorInitExprArgs.clear();
> + }
> + ~InlinedInheritingConstructorScope() {
> + CGF.CurGD = OldCurGD;
> + CGF.CurFuncDecl = OldCurFuncDecl;
> + CGF.CurCodeDecl = OldCurCodeDecl;
> + CGF.CXXABIThisDecl = OldCXXABIThisDecl;
> + CGF.CXXABIThisValue = OldCXXABIThisValue;
> + CGF.CXXThisValue = OldCXXThisValue;
> + CGF.CXXABIThisAlignment = OldCXXABIThisAlignment;
> + CGF.CXXThisAlignment = OldCXXThisAlignment;
> + CGF.ReturnValue = OldReturnValue;
> + CGF.FnRetTy = OldFnRetTy;
> + CGF.CXXInheritedCtorInitExprArgs =
> + std::move(OldCXXInheritedCtorInitExprArgs);
> + }
> +
> + private:
> + CodeGenFunction &CGF;
> + GlobalDecl OldCurGD;
> + const Decl *OldCurFuncDecl;
> + const Decl *OldCurCodeDecl;
> + ImplicitParamDecl *OldCXXABIThisDecl;
> + llvm::Value *OldCXXABIThisValue;
> + llvm::Value *OldCXXThisValue;
> + CharUnits OldCXXABIThisAlignment;
> + CharUnits OldCXXThisAlignment;
> + Address OldReturnValue;
> + QualType OldFnRetTy;
> + CallArgList OldCXXInheritedCtorInitExprArgs;
> + };
> +
> private:
> /// CXXThisDecl - When generating code for a C++ member function,
> /// this will hold the implicit 'this' declaration.
> @@ -1078,6 +1133,10 @@ private:
> /// this expression.
> Address CXXDefaultInitExprThis = Address::invalid();
>
> + /// The values of function arguments to use when evaluating
> + /// CXXInheritedCtorInitExprs within this context.
> + CallArgList CXXInheritedCtorInitExprArgs;
> +
> /// CXXStructorImplicitParamDecl - When generating code for a
> constructor or
> /// destructor, this will hold the implicit argument (e.g. VTT).
> ImplicitParamDecl *CXXStructorImplicitParamDecl;
> @@ -1301,6 +1360,8 @@ public:
>
> const BlockByrefInfo &getBlockByrefInfo(const VarDecl *var);
>
> + QualType BuildFunctionArgList(GlobalDecl GD, FunctionArgList &Args);
> +
> void GenerateCode(GlobalDecl GD, llvm::Function *Fn,
> const CGFunctionInfo &FnInfo);
> /// \brief Emit code for the start of a function.
> @@ -1874,10 +1935,32 @@ public:
> void EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor,
> const FunctionArgList &Args);
>
> + /// Emit a call to an inheriting constructor (that is, one that invokes
> a
> + /// constructor inherited from a base class) by inlining its
> definition. This
> + /// is necessary if the ABI does not support forwarding the arguments
> to the
> + /// base class constructor (because they're variadic or similar).
> + void EmitInlinedInheritingCXXConstructorCall(const CXXConstructorDecl
> *Ctor,
> + CXXCtorType CtorType,
> + bool ForVirtualBase,
> + bool Delegating,
> + CallArgList &Args);
> +
> + /// Emit a call to a constructor inherited from a base class, passing
> the
> + /// current constructor's arguments along unmodified (without even
> making
> + /// a copy).
> + void EmitInheritedCXXConstructorCall(const CXXConstructorDecl *D,
> + bool ForVirtualBase, Address This,
> + bool InheritedFromVBase,
> + const CXXInheritedCtorInitExpr *E);
> +
> void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType
> Type,
> bool ForVirtualBase, bool Delegating,
> Address This, const CXXConstructExpr *E);
>
> + void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType
> Type,
> + bool ForVirtualBase, bool Delegating,
> + Address This, CallArgList &Args);
> +
> /// Emit assumption load for all bases. Requires to be be called only on
> /// most-derived class and not under construction of the object.
> void EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl, Address
> This);
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
> CodeGenModule.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Jun 28 14:03:57 2016
> @@ -765,6 +765,15 @@ CodeGenModule::getFunctionLinkage(Global
> : llvm::GlobalValue::
> LinkOnceODRLinkage;
> }
>
> + if (isa<CXXConstructorDecl>(D) &&
> + cast<CXXConstructorDecl>(D)->isInheritingConstructor() &&
> + Context.getTargetInfo().getCXXABI().isMicrosoft()) {
> + // Our approach to inheriting constructors is fundamentally different
> from
> + // that used by the MS ABI, so keep our inheriting constructor thunks
> + // internal rather than trying to pick an unambiguous mangling for
> them.
> + return llvm::GlobalValue::InternalLinkage;
> + }
> +
> return getLLVMLinkageForDeclarator(D, Linkage,
> /*isConstantVariable=*/false);
> }
>
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
> CodeGenTypes.h?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/CodeGen/CodeGenTypes.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenTypes.h Tue Jun 28 14:03:57 2016
> @@ -205,6 +205,11 @@ public:
> bool isFuncTypeConvertible(const FunctionType *FT);
> bool isFuncParamTypeConvertible(QualType Ty);
>
> + /// Determine if a C++ inheriting constructor should have parameters
> matching
> + /// those of its inherited constructor.
> + bool inheritingCtorHasParams(const InheritedConstructor &Inherited,
> + CXXCtorType Type);
> +
> /// GetFunctionTypeForVTable - Get the LLVM function type for use in a
> vtable,
> /// given a CXXMethodDecl. If the method to has an incomplete return
> type,
> /// and/or incomplete argument types, this will return the opaque type.
>
> Modified: cfe/trunk/lib/Sema/SemaAccess.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaAccess.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaAccess.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaAccess.cpp Tue Jun 28 14:03:57 2016
> @@ -1610,10 +1610,10 @@ Sema::AccessResult Sema::CheckDestructor
> /// Checks access to a constructor.
> Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
> CXXConstructorDecl
> *Constructor,
> + DeclAccessPair Found,
> const InitializedEntity
> &Entity,
> - AccessSpecifier Access,
> bool
> IsCopyBindingRefToTemp) {
> - if (!getLangOpts().AccessControl || Access == AS_public)
> + if (!getLangOpts().AccessControl || Found.getAccess() == AS_public)
> return AR_accessible;
>
> PartialDiagnostic PD(PDiag());
> @@ -1647,17 +1647,17 @@ Sema::AccessResult Sema::CheckConstructo
>
> }
>
> - return CheckConstructorAccess(UseLoc, Constructor, Entity, Access, PD);
> + return CheckConstructorAccess(UseLoc, Constructor, Found, Entity, PD);
> }
>
> /// Checks access to a constructor.
> Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
> CXXConstructorDecl
> *Constructor,
> + DeclAccessPair Found,
> const InitializedEntity
> &Entity,
> - AccessSpecifier Access,
> const PartialDiagnostic
> &PD) {
> if (!getLangOpts().AccessControl ||
> - Access == AS_public)
> + Found.getAccess() == AS_public)
> return AR_accessible;
>
> CXXRecordDecl *NamingClass = Constructor->getParent();
> @@ -1670,15 +1670,23 @@ Sema::AccessResult Sema::CheckConstructo
> // in aggregate initialization. It's not clear whether the object class
> // should be the base class or the derived class in that case.
> CXXRecordDecl *ObjectClass;
> - if (Entity.getKind() == InitializedEntity::EK_Base &&
> !Entity.getParent()) {
> + if ((Entity.getKind() == InitializedEntity::EK_Base ||
> + Entity.getKind() == InitializedEntity::EK_Delegating) &&
> + !Entity.getParent()) {
> ObjectClass = cast<CXXConstructorDecl>(CurContext)->getParent();
> + } else if (auto *Shadow =
> + dyn_cast<ConstructorUsingShadowDecl>(Found.getDecl())) {
> + // If we're using an inheriting constructor to construct an object,
> + // the object class is the derived class, not the base class.
> + ObjectClass = Shadow->getParent();
> } else {
> ObjectClass = NamingClass;
> }
>
> - AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass,
> - DeclAccessPair::make(Constructor, Access),
> - Context.getTypeDeclType(ObjectClass));
> + AccessTarget AccessEntity(
> + Context, AccessTarget::Member, NamingClass,
> + DeclAccessPair::make(Constructor, Found.getAccess()),
> + Context.getTypeDeclType(ObjectClass));
> AccessEntity.setDiag(PD);
>
> return CheckAccess(*this, UseLoc, AccessEntity);
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaDeclCXX.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Jun 28 14:03:57 2016
> @@ -3356,34 +3356,7 @@ BuildImplicitBaseInitializer(Sema &SemaR
> ExprResult BaseInit;
>
> switch (ImplicitInitKind) {
> - case IIK_Inherit: {
> - const CXXRecordDecl *Inherited =
> - Constructor->getInheritedConstructor()->getParent();
> - const CXXRecordDecl *Base = BaseSpec->getType()->
> getAsCXXRecordDecl();
> - if (Base && Inherited->getCanonicalDecl() ==
> Base->getCanonicalDecl()) {
> - // C++11 [class.inhctor]p8:
> - // Each expression in the expression-list is of the form
> - // static_cast<T&&>(p), where p is the name of the corresponding
> - // constructor parameter and T is the declared type of p.
> - SmallVector<Expr*, 16> Args;
> - for (unsigned I = 0, E = Constructor->getNumParams(); I != E; ++I) {
> - ParmVarDecl *PD = Constructor->getParamDecl(I);
> - ExprResult ArgExpr =
> - SemaRef.BuildDeclRefExpr(PD, PD->getType().
> getNonReferenceType(),
> - VK_LValue, SourceLocation());
> - if (ArgExpr.isInvalid())
> - return true;
> - Args.push_back(CastForMoving(SemaRef, ArgExpr.get(),
> PD->getType()));
> - }
> -
> - InitializationKind InitKind = InitializationKind::CreateDirect(
> - Constructor->getLocation(), SourceLocation(), SourceLocation());
> - InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, Args);
> - BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, Args);
> - break;
> - }
> - }
> - // Fall through.
> + case IIK_Inherit:
> case IIK_Default: {
> InitializationKind InitKind
> = InitializationKind::CreateDefault(Constructor->getLocation());
> @@ -3694,12 +3667,12 @@ struct BaseAndFieldInfo {
> BaseAndFieldInfo(Sema &S, CXXConstructorDecl *Ctor, bool ErrorsInInits)
> : S(S), Ctor(Ctor), AnyErrorsInInits(ErrorsInInits) {
> bool Generated = Ctor->isImplicit() || Ctor->isDefaulted();
> - if (Generated && Ctor->isCopyConstructor())
> + if (Ctor->getInheritedConstructor())
> + IIK = IIK_Inherit;
> + else if (Generated && Ctor->isCopyConstructor())
> IIK = IIK_Copy;
> else if (Generated && Ctor->isMoveConstructor())
> IIK = IIK_Move;
> - else if (Ctor->getInheritedConstructor())
> - IIK = IIK_Inherit;
> else
> IIK = IIK_Default;
> }
> @@ -5065,15 +5038,6 @@ void Sema::CheckCompletedCXXClass(CXXRec
> Diag(Record->getLocation(), diag::warn_cxx_ms_struct);
> }
>
> - // Declare inheriting constructors. We do this eagerly here because:
> - // - The standard requires an eager diagnostic for conflicting
> inheriting
> - // constructors from different classes.
> - // - The lazy declaration of the other implicit constructors is so as
> to not
> - // waste space and performance on classes that are not meant to be
> - // instantiated (e.g. meta-functions). This doesn't apply to classes
> that
> - // have inheriting constructors.
> - DeclareInheritingConstructors(Record);
> -
> checkClassLevelDLLAttribute(Record);
> }
>
> @@ -5107,11 +5071,110 @@ static Sema::SpecialMemberOverloadResult
> LHSQuals & Qualifiers::Volatile);
> }
>
> +namespace {
> +struct InheritedConstructorInfo {
> + Sema &S;
> + SourceLocation UseLoc;
> + ConstructorUsingShadowDecl *Shadow;
> +
> + /// A mapping from the base classes through which the constructor was
> + /// inherited to the using shadow declaration in that base class (or a
> null
> + /// pointer if the constructor was declared in that base class).
> + llvm::DenseMap<CXXRecordDecl *, ConstructorUsingShadowDecl *>
> + InheritedFromBases;
> +
> + InheritedConstructorInfo(Sema &S, SourceLocation UseLoc,
> + ConstructorUsingShadowDecl *Shadow)
> + : S(S), UseLoc(UseLoc), Shadow(Shadow) {
> + bool DiagnosedMultipleConstructedBases = false;
> + CXXRecordDecl *ConstructedBase = nullptr;
> + UsingDecl *ConstructedBaseUsing = nullptr;
> +
> + // Find the set of such base class subobjects and check that there's a
> + // unique constructed subobject.
> + for (auto *D : Shadow->redecls()) {
> + auto *DShadow = cast<ConstructorUsingShadowDecl>(D);
> + auto *DNominatedBase = DShadow->getNominatedBaseClass();
> + auto *DConstructedBase = DShadow->getConstructedBaseClass();
> +
> + InheritedFromBases.insert(
> + std::make_pair(DNominatedBase->getCanonicalDecl(),
> + DShadow->getNominatedBaseClassShadowDecl()));
> + if (DShadow->constructsVirtualBase())
> + InheritedFromBases.insert(
> + std::make_pair(DConstructedBase->getCanonicalDecl(),
> + DShadow->getConstructedBaseClassShadowD
> ecl()));
> + else
> + assert(DNominatedBase == DConstructedBase);
> +
> + // [class.inhctor.init]p2:
> + // If the constructor was inherited from multiple base class
> subobjects
> + // of type B, the program is ill-formed.
> + if (!ConstructedBase) {
> + ConstructedBase = DConstructedBase;
> + ConstructedBaseUsing = D->getUsingDecl();
> + } else if (ConstructedBase != DConstructedBase &&
> + !Shadow->isInvalidDecl()) {
> + if (!DiagnosedMultipleConstructedBases) {
> + S.Diag(UseLoc, diag::err_ambiguous_inherited_constructor)
> + << Shadow->getTargetDecl();
> + S.Diag(ConstructedBaseUsing->getLocation(),
> + diag::note_ambiguous_inherited_constructor_using)
> + << ConstructedBase;
> + DiagnosedMultipleConstructedBases = true;
> + }
> + S.Diag(D->getUsingDecl()->getLocation(),
> + diag::note_ambiguous_inherited_constructor_using)
> + << DConstructedBase;
> + }
> + }
> +
> + if (DiagnosedMultipleConstructedBases)
> + Shadow->setInvalidDecl();
> + }
> +
> + /// Find the constructor to use for inherited construction of a base
> class,
> + /// and whether that base class constructor inherits the constructor
> from a
> + /// virtual base class (in which case it won't actually invoke it).
> + std::pair<CXXConstructorDecl *, bool>
> + findConstructorForBase(CXXRecordDecl *Base, CXXConstructorDecl *Ctor)
> const {
> + auto It = InheritedFromBases.find(Base->getCanonicalDecl());
> + if (It == InheritedFromBases.end())
> + return std::make_pair(nullptr, false);
> +
> + // This is an intermediary class.
> + if (It->second)
> + return std::make_pair(
> + S.findInheritingConstructor(UseLoc, Ctor, It->second),
> + It->second->constructsVirtualBase());
> +
> + // This is the base class from which the constructor was inherited.
> + return std::make_pair(Ctor, false);
> + }
> +};
> +}
> +
> /// Is the special member function which would be selected to perform the
> /// specified operation on the specified class type a constexpr
> constructor?
> -static bool specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
> - Sema::CXXSpecialMember CSM,
> - unsigned Quals, bool ConstRHS) {
> +static bool
> +specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
> + Sema::CXXSpecialMember CSM, unsigned Quals,
> + bool ConstRHS,
> + CXXConstructorDecl *InheritedCtor = nullptr,
> + InheritedConstructorInfo *Inherited = nullptr) {
> + // If we're inheriting a constructor, see if we need to call it for
> this base
> + // class.
> + if (InheritedCtor) {
> + assert(CSM == Sema::CXXDefaultConstructor);
> + auto BaseCtor =
> + Inherited->findConstructorForBase(ClassDecl,
> InheritedCtor).first;
> + if (BaseCtor)
> + return BaseCtor->isConstexpr();
> + }
> +
> + if (CSM == Sema::CXXDefaultConstructor)
> + return ClassDecl->hasConstexprDefaultConstructor();
> +
> Sema::SpecialMemberOverloadResult *SMOR =
> lookupCallFromSpecialMember(S, ClassDecl, CSM, Quals, ConstRHS);
> if (!SMOR || !SMOR->getMethod())
> @@ -5123,9 +5186,10 @@ static bool specialMemberIsConstexpr(Sem
>
> /// Determine whether the specified special member function would be
> constexpr
> /// if it were implicitly defined.
> -static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl
> *ClassDecl,
> - Sema::CXXSpecialMember CSM,
> - bool ConstArg) {
> +static bool defaultedSpecialMemberIsConstexpr(
> + Sema &S, CXXRecordDecl *ClassDecl, Sema::CXXSpecialMember CSM,
> + bool ConstArg, CXXConstructorDecl *InheritedCtor = nullptr,
> + InheritedConstructorInfo *Inherited = nullptr) {
> if (!S.getLangOpts().CPlusPlus11)
> return false;
>
> @@ -5134,6 +5198,8 @@ static bool defaultedSpecialMemberIsCons
> bool Ctor = true;
> switch (CSM) {
> case Sema::CXXDefaultConstructor:
> + if (Inherited)
> + break;
> // Since default constructor lookup is essentially trivial (and cannot
> // involve, for instance, template instantiation), we compute whether
> a
> // defaulted default constructor is constexpr directly within
> CXXRecordDecl.
> @@ -5168,7 +5234,10 @@ static bool defaultedSpecialMemberIsCons
> // will be initialized (if the constructor isn't deleted), we just
> don't know
> // which one.
> if (Ctor && ClassDecl->isUnion())
> - return true;
> + return CSM == Sema::CXXDefaultConstructor
> + ? ClassDecl->hasInClassInitializer() ||
> + !ClassDecl->hasVariantMembers()
> + : true;
>
> // -- the class shall not have any virtual base classes;
> if (Ctor && ClassDecl->getNumVBases())
> @@ -5188,7 +5257,8 @@ static bool defaultedSpecialMemberIsCons
> if (!BaseType) continue;
>
> CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->
> getDecl());
> - if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg))
> + if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg,
> + InheritedCtor, Inherited))
> return false;
> }
>
> @@ -5202,6 +5272,8 @@ static bool defaultedSpecialMemberIsCons
> for (const auto *F : ClassDecl->fields()) {
> if (F->isInvalidDecl())
> continue;
> + if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer())
> + continue;
> QualType BaseType = S.Context.getBaseElementType(F->getType());
> if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
> CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->
> getDecl());
> @@ -5209,6 +5281,8 @@ static bool defaultedSpecialMemberIsCons
> BaseType.getCVRQualifiers(),
> ConstArg && !F->isMutable()))
> return false;
> + } else if (CSM == Sema::CXXDefaultConstructor) {
> + return false;
> }
> }
>
> @@ -5236,7 +5310,8 @@ computeImplicitExceptionSpec(Sema &S, So
> }
> assert(cast<CXXConstructorDecl>(MD)->getInheritedConstructor() &&
> "only special members have implicit exception specs");
> - return S.ComputeInheritingCtorExceptionSpec(cast<CXXConstructorDecl>(
> MD));
> + return S.ComputeInheritingCtorExceptionSpec(Loc,
> +
> cast<CXXConstructorDecl>(MD));
> }
>
> static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S,
> @@ -6501,14 +6576,12 @@ void Sema::ActOnFinishCXXMemberSpecifica
> /// [special]p1). This routine can only be executed just before the
> /// definition of the class is complete.
> void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl)
> {
> - if (!ClassDecl->hasUserDeclaredConstructor())
> + if (ClassDecl->needsImplicitDefaultConstructor()) {
> ++ASTContext::NumImplicitDefaultConstructors;
>
> - // If this class inherited any constructors, declare the default
> constructor
> - // now in case it displaces one from a base class.
> - if (ClassDecl->needsImplicitDefaultConstructor() &&
> - ClassDecl->hasInheritedConstructor())
> - DeclareImplicitDefaultConstructor(ClassDecl);
> + if (ClassDecl->hasInheritedConstructor())
> + DeclareImplicitDefaultConstructor(ClassDecl);
> + }
>
> if (ClassDecl->needsImplicitCopyConstructor()) {
> ++ASTContext::NumImplicitCopyConstructors;
> @@ -7928,12 +8001,21 @@ bool Sema::CheckUsingShadowDecl(UsingDec
> return true;
> }
>
> +/// Determine whether a direct base class is a virtual base class.
> +static bool isVirtualDirectBase(CXXRecordDecl *Derived, CXXRecordDecl
> *Base) {
> + if (!Derived->getNumVBases())
> + return false;
> + for (auto &B : Derived->bases())
> + if (B.getType()->getAsCXXRecordDecl() == Base)
> + return B.isVirtual();
> + llvm_unreachable("not a direct base class");
> +}
> +
> /// Builds a shadow declaration corresponding to a 'using' declaration.
> UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
> UsingDecl *UD,
> NamedDecl *Orig,
> UsingShadowDecl *PrevDecl) {
> -
> // If we resolved to another shadow declaration, just coalesce them.
> NamedDecl *Target = Orig;
> if (isa<UsingShadowDecl>(Target)) {
> @@ -7941,9 +8023,21 @@ UsingShadowDecl *Sema::BuildUsingShadowD
> assert(!isa<UsingShadowDecl>(Target) && "nested shadow declaration");
> }
>
> - UsingShadowDecl *Shadow
> - = UsingShadowDecl::Create(Context, CurContext,
> - UD->getLocation(), UD, Target);
> + NamedDecl *NonTemplateTarget = Target;
> + if (auto *TargetTD = dyn_cast<TemplateDecl>(Target))
> + NonTemplateTarget = TargetTD->getTemplatedDecl();
> +
> + UsingShadowDecl *Shadow;
> + if (isa<CXXConstructorDecl>(NonTemplateTarget)) {
> + bool IsVirtualBase =
> + isVirtualDirectBase(cast<CXXRecordDecl>(CurContext),
> + UD->getQualifier()->getAsRecordDecl());
> + Shadow = ConstructorUsingShadowDecl::Create(
> + Context, CurContext, UD->getLocation(), UD, Orig, IsVirtualBase);
> + } else {
> + Shadow = UsingShadowDecl::Create(Context, CurContext,
> UD->getLocation(), UD,
> + Target);
> + }
> UD->addShadowDecl(Shadow);
>
> Shadow->setAccess(UD->getAccess());
> @@ -8128,8 +8222,17 @@ NamedDecl *Sema::BuildUsingDeclaration(S
> return nullptr;
> }
>
> + // For an inheriting constructor declaration, the name of the using
> + // declaration is the name of a constructor in this class, not in the
> + // base class.
> + DeclarationNameInfo UsingName = NameInfo;
> + if (UsingName.getName().getNameKind() == DeclarationName::
> CXXConstructorName)
> + if (auto *RD = dyn_cast<CXXRecordDecl>(CurContext))
> + UsingName.setName(Context.DeclarationNames.getCXXConstructorName(
> + Context.getCanonicalType(Context.getRecordType(RD))));
> +
> // Do the redeclaration lookup in the current scope.
> - LookupResult Previous(*this, NameInfo, LookupUsingDeclName,
> + LookupResult Previous(*this, UsingName, LookupUsingDeclName,
> ForRedeclaration);
> Previous.setHideTags(false);
> if (S) {
> @@ -8186,8 +8289,8 @@ NamedDecl *Sema::BuildUsingDeclaration(S
>
> auto Build = [&](bool Invalid) {
> UsingDecl *UD =
> - UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc,
> NameInfo,
> - HasTypenameKeyword);
> + UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc,
> + UsingName, HasTypenameKeyword);
> UD->setAccess(AS);
> CurContext->addDecl(UD);
> UD->setInvalidDecl(Invalid);
> @@ -8242,6 +8345,9 @@ NamedDecl *Sema::BuildUsingDeclaration(S
> // If we corrected to an inheriting constructor, handle it as one.
> auto *RD = dyn_cast<CXXRecordDecl>(ND);
> if (RD && RD->isInjectedClassName()) {
> + // The parent of the injected class name is the class itself.
> + RD = cast<CXXRecordDecl>(RD->getParent());
> +
> // Fix up the information we'll use to build the using
> declaration.
> if (Corrected.WillReplaceSpecifier()) {
> NestedNameSpecifierLocBuilder Builder;
> @@ -8250,14 +8356,19 @@ NamedDecl *Sema::BuildUsingDeclaration(S
> QualifierLoc = Builder.getWithLocInContext(Context);
> }
>
> - NameInfo.setName(Context.DeclarationNames.getCXXConstructorName(
> - Context.getCanonicalType(Context.getRecordType(RD))));
> - NameInfo.setNamedTypeInfo(nullptr);
> + // In this case, the name we introduce is the name of a derived
> class
> + // constructor.
> + auto *CurClass = cast<CXXRecordDecl>(CurContext);
> + UsingName.setName(Context.DeclarationNames.getCXXConstructorName(
> + Context.getCanonicalType(Context.getRecordType(CurClass))));
> + UsingName.setNamedTypeInfo(nullptr);
> for (auto *Ctor : LookupConstructors(RD))
> R.addDecl(Ctor);
> + R.resolveKind();
> } else {
> - // FIXME: Pick up all the declarations if we found an overloaded
> function.
> - NameInfo.setName(ND->getDeclName());
> + // FIXME: Pick up all the declarations if we found an overloaded
> + // function.
> + UsingName.setName(ND->getDeclName());
> R.addDecl(ND);
> }
> } else {
> @@ -8310,17 +8421,16 @@ NamedDecl *Sema::BuildUsingDeclaration(S
>
> UsingDecl *UD = BuildValid();
>
> - // The normal rules do not apply to inheriting constructor declarations.
> - if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName)
> {
> + // Some additional rules apply to inheriting constructors.
> + if (UsingName.getName().getNameKind() ==
> + DeclarationName::CXXConstructorName) {
> // Suppress access diagnostics; the access check is instead performed
> at the
> // point of use for an inheriting constructor.
> R.suppressDiagnostics();
> - CheckInheritingConstructorUsingDecl(UD);
> - return UD;
> + if (CheckInheritingConstructorUsingDecl(UD))
> + return UD;
> }
>
> - // Otherwise, look up the target name.
> -
> for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
> UsingShadowDecl *PrevDecl = nullptr;
> if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl))
> @@ -8895,7 +9005,8 @@ Sema::ComputeDefaultedDefaultCtorExcepti
> }
>
> Sema::ImplicitExceptionSpecification
> -Sema::ComputeInheritingCtorExceptionSpec(CXXConstructorDecl *CD) {
> +Sema::ComputeInheritingCtorExceptionSpec(SourceLocation Loc,
> + CXXConstructorDecl *CD) {
> CXXRecordDecl *ClassDecl = CD->getParent();
>
> // C++ [except.spec]p14:
> @@ -8904,36 +9015,26 @@ Sema::ComputeInheritingCtorExceptionSpec
> if (ClassDecl->isInvalidDecl())
> return ExceptSpec;
>
> - // Inherited constructor.
> - const CXXConstructorDecl *InheritedCD = CD->getInheritedConstructor();
> - const CXXRecordDecl *InheritedDecl = InheritedCD->getParent();
> - // FIXME: Copying or moving the parameters could add extra exceptions
> to the
> - // set, as could the default arguments for the inherited constructor.
> This
> - // will be addressed when we implement the resolution of core issue
> 1351.
> - ExceptSpec.CalledDecl(CD->getLocStart(), InheritedCD);
> + auto Inherited = CD->getInheritedConstructor();
> + InheritedConstructorInfo ICI(*this, Loc, Inherited.getShadowDecl());
>
> - // Direct base-class constructors.
> - for (const auto &B : ClassDecl->bases()) {
> - if (B.isVirtual()) // Handled below.
> - continue;
> -
> - if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
> - CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->
> getDecl());
> - if (BaseClassDecl == InheritedDecl)
> + // Direct and virtual base-class constructors.
> + for (bool VBase : {false, true}) {
> + for (CXXBaseSpecifier &B :
> + VBase ? ClassDecl->vbases() : ClassDecl->bases()) {
> + // Don't visit direct vbases twice.
> + if (B.isVirtual() != VBase)
> continue;
> - CXXConstructorDecl *Constructor = LookupDefaultConstructor(
> BaseClassDecl);
> - if (Constructor)
> - ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
> - }
> - }
>
> - // Virtual base-class constructors.
> - for (const auto &B : ClassDecl->vbases()) {
> - if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
> - CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->
> getDecl());
> - if (BaseClassDecl == InheritedDecl)
> + CXXRecordDecl *BaseClass = B.getType()->getAsCXXRecordDecl();
> + if (!BaseClass)
> continue;
> - CXXConstructorDecl *Constructor = LookupDefaultConstructor(
> BaseClassDecl);
> +
> + CXXConstructorDecl *Constructor =
> + ICI.findConstructorForBase(BaseClass,
> Inherited.getConstructor())
> + .first;
> + if (!Constructor)
> + Constructor = LookupDefaultConstructor(BaseClass);
> if (Constructor)
> ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
> }
> @@ -9111,325 +9212,156 @@ void Sema::ActOnFinishDelayedMemberIniti
> CheckDelayedMemberExceptionSpecs();
> }
>
> -namespace {
> -/// Information on inheriting constructors to declare.
> -class InheritingConstructorInfo {
> -public:
> - InheritingConstructorInfo(Sema &SemaRef, CXXRecordDecl *Derived)
> - : SemaRef(SemaRef), Derived(Derived) {
> - // Mark the constructors that we already have in the derived class.
> - //
> - // C++11 [class.inhctor]p3: [...] a constructor is implicitly
> declared [...]
> - // unless there is a user-declared constructor with the same
> signature in
> - // the class where the using-declaration appears.
> - visitAll(Derived, &InheritingConstructorInfo::noteDeclaredInDerived);
> - }
> -
> - void inheritAll(CXXRecordDecl *RD) {
> - visitAll(RD, &InheritingConstructorInfo::inherit);
> - }
> -
> -private:
> - /// Information about an inheriting constructor.
> - struct InheritingConstructor {
> - InheritingConstructor()
> - : DeclaredInDerived(false), BaseCtor(nullptr), DerivedCtor(nullptr)
> {}
> -
> - /// If \c true, a constructor with this signature is already declared
> - /// in the derived class.
> - bool DeclaredInDerived;
> -
> - /// The constructor which is inherited.
> - const CXXConstructorDecl *BaseCtor;
> -
> - /// The derived constructor we declared.
> - CXXConstructorDecl *DerivedCtor;
> - };
> -
> - /// Inheriting constructors with a given canonical type. There can be at
> - /// most one such non-template constructor, and any number of templated
> - /// constructors.
> - struct InheritingConstructorsForType {
> - InheritingConstructor NonTemplate;
> - SmallVector<std::pair<TemplateParameterList *,
> InheritingConstructor>, 4>
> - Templates;
> -
> - InheritingConstructor &getEntry(Sema &S, const CXXConstructorDecl
> *Ctor) {
> - if (FunctionTemplateDecl *FTD = Ctor->
> getDescribedFunctionTemplate()) {
> - TemplateParameterList *ParamList = FTD->getTemplateParameters();
> - for (unsigned I = 0, N = Templates.size(); I != N; ++I)
> - if (S.TemplateParameterListsAreEqual(ParamList,
> Templates[I].first,
> - false,
> S.TPL_TemplateMatch))
> - return Templates[I].second;
> - Templates.push_back(std::make_pair(ParamList,
> InheritingConstructor()));
> - return Templates.back().second;
> - }
> -
> - return NonTemplate;
> - }
> - };
> -
> - /// Get or create the inheriting constructor record for a constructor.
> - InheritingConstructor &getEntry(const CXXConstructorDecl *Ctor,
> - QualType CtorType) {
> - return Map[CtorType.getCanonicalType()->castAs<FunctionProtoType>()]
> - .getEntry(SemaRef, Ctor);
> - }
> +/// Find or create the fake constructor we synthesize to model
> constructing an
> +/// object of a derived class via a constructor of a base class.
> +CXXConstructorDecl *
> +Sema::findInheritingConstructor(SourceLocation Loc,
> + CXXConstructorDecl *BaseCtor,
> + ConstructorUsingShadowDecl *Shadow) {
> + CXXRecordDecl *Derived = Shadow->getParent();
> + SourceLocation UsingLoc = Shadow->getLocation();
> +
> + // FIXME: Add a new kind of DeclarationName for an inherited
> constructor.
> + // For now we use the name of the base class constructor as a member of
> the
> + // derived class to indicate a (fake) inherited constructor name.
> + DeclarationName Name = BaseCtor->getDeclName();
> +
> + // Check to see if we already have a fake constructor for this inherited
> + // constructor call.
> + for (NamedDecl *Ctor : Derived->lookup(Name))
> + if (declaresSameEntity(cast<CXXConstructorDecl>(Ctor)
> + ->getInheritedConstructor()
> + .getConstructor(),
> + BaseCtor))
> + return cast<CXXConstructorDecl>(Ctor);
> +
> + DeclarationNameInfo NameInfo(Name, UsingLoc);
> + TypeSourceInfo *TInfo =
> + Context.getTrivialTypeSourceInfo(BaseCtor->getType(), UsingLoc);
> + FunctionProtoTypeLoc ProtoLoc =
> + TInfo->getTypeLoc().IgnoreParens().castAs<FunctionProtoTypeLoc>();
> +
> + // Check the inherited constructor is valid and find the list of base
> classes
> + // from which it was inherited.
> + InheritedConstructorInfo ICI(*this, Loc, Shadow);
> +
> + bool Constexpr =
> + BaseCtor->isConstexpr() &&
> + defaultedSpecialMemberIsConstexpr(*this, Derived,
> CXXDefaultConstructor,
> + false, BaseCtor, &ICI);
> +
> + CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create(
> + Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo,
> + BaseCtor->isExplicit(), /*Inline=*/true,
> + /*ImplicitlyDeclared=*/true, Constexpr,
> + InheritedConstructor(Shadow, BaseCtor));
> + if (Shadow->isInvalidDecl())
> + DerivedCtor->setInvalidDecl();
> +
> + // Build an unevaluated exception specification for this fake
> constructor.
> + const FunctionProtoType *FPT = TInfo->getType()->castAs<
> FunctionProtoType>();
> + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
> + EPI.ExceptionSpec.Type = EST_Unevaluated;
> + EPI.ExceptionSpec.SourceDecl = DerivedCtor;
> + DerivedCtor->setType(Context.getFunctionType(FPT->getReturnType(),
> + FPT->getParamTypes(),
> EPI));
> +
> + // Build the parameter declarations.
> + SmallVector<ParmVarDecl *, 16> ParamDecls;
> + for (unsigned I = 0, N = FPT->getNumParams(); I != N; ++I) {
> + TypeSourceInfo *TInfo =
> + Context.getTrivialTypeSourceInfo(FPT->getParamType(I), UsingLoc);
> + ParmVarDecl *PD = ParmVarDecl::Create(
> + Context, DerivedCtor, UsingLoc, UsingLoc,
> /*IdentifierInfo=*/nullptr,
> + FPT->getParamType(I), TInfo, SC_None, /*DefaultArg=*/nullptr);
> + PD->setScopeInfo(0, I);
> + PD->setImplicit();
> + // Ensure attributes are propagated onto parameters (this matters for
> + // format, pass_object_size, ...).
> + mergeDeclAttributes(PD, BaseCtor->getParamDecl(I));
> + ParamDecls.push_back(PD);
> + ProtoLoc.setParam(I, PD);
> + }
> +
> + // Set up the new constructor.
> + assert(!BaseCtor->isDeleted() && "should not use deleted constructor");
> + DerivedCtor->setAccess(BaseCtor->getAccess());
> + DerivedCtor->setParams(ParamDecls);
> + Derived->addDecl(DerivedCtor);
> + return DerivedCtor;
> +}
>
> - typedef void (InheritingConstructorInfo::*VisitFn)(const
> CXXConstructorDecl*);
> -
> - /// Process all constructors for a class.
> - void visitAll(const CXXRecordDecl *RD, VisitFn Callback) {
> - for (const auto *Ctor : RD->ctors())
> - (this->*Callback)(Ctor);
> - for (CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl>
> - I(RD->decls_begin()), E(RD->decls_end());
> - I != E; ++I) {
> - const FunctionDecl *FD = (*I)->getTemplatedDecl();
> - if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(
> FD))
> - (this->*Callback)(CD);
> - }
> - }
> +void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation,
> + CXXConstructorDecl *Constructor) {
> + CXXRecordDecl *ClassDecl = Constructor->getParent();
> + assert(Constructor->getInheritedConstructor() &&
> + !Constructor->doesThisDeclarationHaveABody() &&
> + !Constructor->isDeleted());
> + if (Constructor->isInvalidDecl())
> + return;
>
> - /// Note that a constructor (or constructor template) was declared in
> Derived.
> - void noteDeclaredInDerived(const CXXConstructorDecl *Ctor) {
> - getEntry(Ctor, Ctor->getType()).DeclaredInDerived = true;
> - }
> + ConstructorUsingShadowDecl *Shadow =
> + Constructor->getInheritedConstructor().getShadowDecl();
> + CXXConstructorDecl *InheritedCtor =
> + Constructor->getInheritedConstructor().getConstructor();
>
> - /// Inherit a single constructor.
> - void inherit(const CXXConstructorDecl *Ctor) {
> - const FunctionProtoType *CtorType =
> - Ctor->getType()->castAs<FunctionProtoType>();
> - ArrayRef<QualType> ArgTypes = CtorType->getParamTypes();
> - FunctionProtoType::ExtProtoInfo EPI = CtorType->getExtProtoInfo();
> + // [class.inhctor.init]p1:
> + // initialization proceeds as if a defaulted default constructor is
> used to
> + // initialize the D object and each base class subobject from which
> the
> + // constructor was inherited
>
> - SourceLocation UsingLoc = getUsingLoc(Ctor->getParent());
> + InheritedConstructorInfo ICI(*this, CurrentLocation, Shadow);
> + CXXRecordDecl *RD = Shadow->getParent();
> + SourceLocation InitLoc = Shadow->getLocation();
>
> - // Core issue (no number yet): the ellipsis is always discarded.
> - if (EPI.Variadic) {
> - SemaRef.Diag(UsingLoc, diag::warn_using_decl_constructor_ellipsis);
> - SemaRef.Diag(Ctor->getLocation(),
> - diag::note_using_decl_constructor_ellipsis);
> - EPI.Variadic = false;
> - }
> + // Initializations are performed "as if by a defaulted default
> constructor",
> + // so enter the appropriate scope.
> + SynthesizedFunctionScope Scope(*this, Constructor);
> + DiagnosticErrorTrap Trap(Diags);
>
> - // Declare a constructor for each number of parameters.
> - //
> - // C++11 [class.inhctor]p1:
> - // The candidate set of inherited constructors from the class X
> named in
> - // the using-declaration consists of [... modulo defects ...] for
> each
> - // constructor or constructor template of X, the set of
> constructors or
> - // constructor templates that results from omitting any ellipsis
> parameter
> - // specification and successively omitting parameters with a default
> - // argument from the end of the parameter-type-list
> - unsigned MinParams = minParamsToInherit(Ctor);
> - unsigned Params = Ctor->getNumParams();
> - if (Params >= MinParams) {
> - do
> - declareCtor(UsingLoc, Ctor,
> - SemaRef.Context.getFunctionType(
> - Ctor->getReturnType(), ArgTypes.slice(0, Params),
> EPI));
> - while (Params > MinParams &&
> - Ctor->getParamDecl(--Params)->hasDefaultArg());
> - }
> - }
> -
> - /// Find the using-declaration which specified that we should inherit
> the
> - /// constructors of \p Base.
> - SourceLocation getUsingLoc(const CXXRecordDecl *Base) {
> - // No fancy lookup required; just look for the base constructor name
> - // directly within the derived class.
> - ASTContext &Context = SemaRef.Context;
> - DeclarationName Name = Context.DeclarationNames.
> getCXXConstructorName(
> - Context.getCanonicalType(Context.getRecordType(Base)));
> - DeclContext::lookup_result Decls = Derived->lookup(Name);
> - return Decls.empty() ? Derived->getLocation() :
> Decls[0]->getLocation();
> - }
> -
> - unsigned minParamsToInherit(const CXXConstructorDecl *Ctor) {
> - // C++11 [class.inhctor]p3:
> - // [F]or each constructor template in the candidate set of inherited
> - // constructors, a constructor template is implicitly declared
> - if (Ctor->getDescribedFunctionTemplate())
> - return 0;
> -
> - // For each non-template constructor in the candidate set of
> inherited
> - // constructors other than a constructor having no parameters or a
> - // copy/move constructor having a single parameter, a constructor is
> - // implicitly declared [...]
> - if (Ctor->getNumParams() == 0)
> - return 1;
> - if (Ctor->isCopyOrMoveConstructor())
> - return 2;
> -
> - // Per discussion on core reflector, never inherit a constructor which
> - // would become a default, copy, or move constructor of Derived
> either.
> - const ParmVarDecl *PD = Ctor->getParamDecl(0);
> - const ReferenceType *RT = PD->getType()->getAs<ReferenceType>();
> - return (RT && RT->getPointeeCXXRecordDecl() == Derived) ? 2 : 1;
> - }
> -
> - /// Declare a single inheriting constructor, inheriting the specified
> - /// constructor, with the given type.
> - void declareCtor(SourceLocation UsingLoc, const CXXConstructorDecl
> *BaseCtor,
> - QualType DerivedType) {
> - InheritingConstructor &Entry = getEntry(BaseCtor, DerivedType);
> -
> - // C++11 [class.inhctor]p3:
> - // ... a constructor is implicitly declared with the same
> constructor
> - // characteristics unless there is a user-declared constructor with
> - // the same signature in the class where the using-declaration
> appears
> - if (Entry.DeclaredInDerived)
> - return;
> + // Build explicit initializers for all base classes from which the
> + // constructor was inherited.
> + SmallVector<CXXCtorInitializer*, 8> Inits;
> + for (bool VBase : {false, true}) {
> + for (CXXBaseSpecifier &B : VBase ? RD->vbases() : RD->bases()) {
> + if (B.isVirtual() != VBase)
> + continue;
>
> - // C++11 [class.inhctor]p7:
> - // If two using-declarations declare inheriting constructors with
> the
> - // same signature, the program is ill-formed
> - if (Entry.DerivedCtor) {
> - if (BaseCtor->getParent() != Entry.BaseCtor->getParent()) {
> - // Only diagnose this once per constructor.
> - if (Entry.DerivedCtor->isInvalidDecl())
> - return;
> - Entry.DerivedCtor->setInvalidDecl();
> -
> - SemaRef.Diag(UsingLoc, diag::err_using_decl_
> constructor_conflict);
> - SemaRef.Diag(BaseCtor->getLocation(),
> - diag::note_using_decl_constructor_conflict_current_
> ctor);
> - SemaRef.Diag(Entry.BaseCtor->getLocation(),
> - diag::note_using_decl_constructor_conflict_previous_
> ctor);
> - SemaRef.Diag(Entry.DerivedCtor->getLocation(),
> - diag::note_using_decl_constructor_conflict_previous_
> using);
> - } else {
> - // Core issue (no number): if the same inheriting constructor is
> - // produced by multiple base class constructors from the same base
> - // class, the inheriting constructor is defined as deleted.
> - SemaRef.SetDeclDeleted(Entry.DerivedCtor, UsingLoc);
> - }
> + auto *BaseRD = B.getType()->getAsCXXRecordDecl();
> + if (!BaseRD)
> + continue;
>
> - return;
> - }
> + auto BaseCtor = ICI.findConstructorForBase(BaseRD, InheritedCtor);
> + if (!BaseCtor.first)
> + continue;
>
> - ASTContext &Context = SemaRef.Context;
> - DeclarationName Name = Context.DeclarationNames.
> getCXXConstructorName(
> - Context.getCanonicalType(Context.getRecordType(Derived)));
> - DeclarationNameInfo NameInfo(Name, UsingLoc);
> -
> - TemplateParameterList *TemplateParams = nullptr;
> - if (const FunctionTemplateDecl *FTD =
> - BaseCtor->getDescribedFunctionTemplate()) {
> - TemplateParams = FTD->getTemplateParameters();
> - // We're reusing template parameters from a different DeclContext.
> This
> - // is questionable at best, but works out because the template
> depth in
> - // both places is guaranteed to be 0.
> - // FIXME: Rebuild the template parameters in the new context, and
> - // transform the function type to refer to them.
> - }
> + MarkFunctionReferenced(CurrentLocation, BaseCtor.first);
> + ExprResult Init = new (Context) CXXInheritedCtorInitExpr(
> + InitLoc, B.getType(), BaseCtor.first, VBase, BaseCtor.second);
>
> - // Build type source info pointing at the using-declaration. This is
> - // required by template instantiation.
> - TypeSourceInfo *TInfo =
> - Context.getTrivialTypeSourceInfo(DerivedType, UsingLoc);
> - FunctionProtoTypeLoc ProtoLoc =
> - TInfo->getTypeLoc().IgnoreParens().castAs<
> FunctionProtoTypeLoc>();
> -
> - CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create(
> - Context, Derived, UsingLoc, NameInfo, DerivedType,
> - TInfo, BaseCtor->isExplicit(), /*Inline=*/true,
> - /*ImplicitlyDeclared=*/true, /*Constexpr=*/BaseCtor->
> isConstexpr());
> -
> - // Build an unevaluated exception specification for this constructor.
> - const FunctionProtoType *FPT = DerivedType->castAs<
> FunctionProtoType>();
> - FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
> - EPI.ExceptionSpec.Type = EST_Unevaluated;
> - EPI.ExceptionSpec.SourceDecl = DerivedCtor;
> - DerivedCtor->setType(Context.getFunctionType(FPT->getReturnType(),
> - FPT->getParamTypes(),
> EPI));
> -
> - // Build the parameter declarations.
> - SmallVector<ParmVarDecl *, 16> ParamDecls;
> - for (unsigned I = 0, N = FPT->getNumParams(); I != N; ++I) {
> - TypeSourceInfo *TInfo =
> - Context.getTrivialTypeSourceInfo(FPT->getParamType(I),
> UsingLoc);
> - ParmVarDecl *PD = ParmVarDecl::Create(
> - Context, DerivedCtor, UsingLoc, UsingLoc,
> /*IdentifierInfo=*/nullptr,
> - FPT->getParamType(I), TInfo, SC_None, /*DefaultArg=*/nullptr);
> - PD->setScopeInfo(0, I);
> - PD->setImplicit();
> - ParamDecls.push_back(PD);
> - ProtoLoc.setParam(I, PD);
> - }
> -
> - // Set up the new constructor.
> - DerivedCtor->setAccess(BaseCtor->getAccess());
> - DerivedCtor->setParams(ParamDecls);
> - DerivedCtor->setInheritedConstructor(BaseCtor);
> - if (BaseCtor->isDeleted())
> - SemaRef.SetDeclDeleted(DerivedCtor, UsingLoc);
> -
> - // If this is a constructor template, build the template declaration.
> - if (TemplateParams) {
> - FunctionTemplateDecl *DerivedTemplate =
> - FunctionTemplateDecl::Create(SemaRef.Context, Derived,
> UsingLoc, Name,
> - TemplateParams, DerivedCtor);
> - DerivedTemplate->setAccess(BaseCtor->getAccess());
> - DerivedCtor->setDescribedFunctionTemplate(DerivedTemplate);
> - Derived->addDecl(DerivedTemplate);
> - } else {
> - Derived->addDecl(DerivedCtor);
> + auto *TInfo = Context.getTrivialTypeSourceInfo(B.getType(),
> InitLoc);
> + Inits.push_back(new (Context) CXXCtorInitializer(
> + Context, TInfo, VBase, InitLoc, Init.get(), InitLoc,
> + SourceLocation()));
> }
> -
> - Entry.BaseCtor = BaseCtor;
> - Entry.DerivedCtor = DerivedCtor;
> }
>
> - Sema &SemaRef;
> - CXXRecordDecl *Derived;
> - typedef llvm::DenseMap<const Type *, InheritingConstructorsForType>
> MapType;
> - MapType Map;
> -};
> -}
> -
> -void Sema::DeclareInheritingConstructors(CXXRecordDecl *ClassDecl) {
> - // Defer declaring the inheriting constructors until the class is
> - // instantiated.
> - if (ClassDecl->isDependentContext())
> - return;
> -
> - // Find base classes from which we might inherit constructors.
> - SmallVector<CXXRecordDecl*, 4> InheritedBases;
> - for (const auto &BaseIt : ClassDecl->bases())
> - if (BaseIt.getInheritConstructors())
> - InheritedBases.push_back(BaseIt.getType()->getAsCXXRecordDecl());
> -
> - // Go no further if we're not inheriting any constructors.
> - if (InheritedBases.empty())
> - return;
> -
> - // Declare the inherited constructors.
> - InheritingConstructorInfo ICI(*this, ClassDecl);
> - for (unsigned I = 0, N = InheritedBases.size(); I != N; ++I)
> - ICI.inheritAll(InheritedBases[I]);
> -}
> + // We now proceed as if for a defaulted default constructor, with the
> relevant
> + // initializers replaced.
>
> -void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation,
> - CXXConstructorDecl *Constructor) {
> - CXXRecordDecl *ClassDecl = Constructor->getParent();
> - assert(Constructor->getInheritedConstructor() &&
> - !Constructor->doesThisDeclarationHaveABody() &&
> - !Constructor->isDeleted());
> -
> - SynthesizedFunctionScope Scope(*this, Constructor);
> - DiagnosticErrorTrap Trap(Diags);
> - if (SetCtorInitializers(Constructor, /*AnyErrors=*/false) ||
> - Trap.hasErrorOccurred()) {
> - Diag(CurrentLocation, diag::note_inhctor_synthesized_at)
> - << Context.getTagDeclType(ClassDecl);
> + bool HadError = SetCtorInitializers(Constructor, /*AnyErrors*/false,
> Inits);
> + if (HadError || Trap.hasErrorOccurred()) {
> + Diag(CurrentLocation, diag::note_inhctor_synthesized_at) << RD;
> Constructor->setInvalidDecl();
> return;
> }
>
> - SourceLocation Loc = Constructor->getLocation();
> - Constructor->setBody(new (Context) CompoundStmt(Loc));
> + // The exception specification is needed because we are defining the
> + // function.
> + ResolveExceptionSpec(CurrentLocation,
> + Constructor->getType()->
> castAs<FunctionProtoType>());
> +
> + Constructor->setBody(new (Context) CompoundStmt(InitLoc));
>
> Constructor->markUsed(Context);
> MarkVTableUsed(CurrentLocation, ClassDecl);
> @@ -9437,8 +9369,9 @@ void Sema::DefineInheritingConstructor(S
> if (ASTMutationListener *L = getASTMutationListener()) {
> L->CompletedImplicitDefinition(Constructor);
> }
> -}
>
> + DiagnoseUninitializedFields(*this, Constructor);
> +}
>
> Sema::ImplicitExceptionSpecification
> Sema::ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD) {
> @@ -11481,10 +11414,11 @@ Sema::BuildCXXConstructExpr(SourceLocati
> // with the same cv-unqualified type, the copy/move operation
> // can be omitted by constructing the temporary object
> // directly into the target of the omitted copy/move
> - if (ConstructKind == CXXConstructExpr::CK_Complete &&
> + if (ConstructKind == CXXConstructExpr::CK_Complete && Constructor &&
> Constructor->isCopyOrMoveConstructor() &&
> hasOneRealArgument(ExprArgs)) {
> Expr *SubExpr = ExprArgs[0];
> - Elidable = SubExpr->isTemporaryObject(Context,
> Constructor->getParent());
> + Elidable = SubExpr->isTemporaryObject(
> + Context, cast<CXXRecordDecl>(FoundDecl->getDeclContext()));
> }
>
> return BuildCXXConstructExpr(ConstructLoc, DeclInitType,
> @@ -11507,6 +11441,9 @@ Sema::BuildCXXConstructExpr(SourceLocati
> bool RequiresZeroInit,
> unsigned ConstructKind,
> SourceRange ParenRange) {
> + if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl))
> + Constructor = findInheritingConstructor(ConstructLoc, Constructor,
> Shadow);
> +
> return BuildCXXConstructExpr(
> ConstructLoc, DeclInitType, Constructor, Elidable, ExprArgs,
> HadMultipleCandidates, IsListInitialization,
> IsStdInitListInitialization,
> @@ -11526,7 +11463,12 @@ Sema::BuildCXXConstructExpr(SourceLocati
> bool RequiresZeroInit,
> unsigned ConstructKind,
> SourceRange ParenRange) {
> + assert(declaresSameEntity(
> + Constructor->getParent(),
> + DeclInitType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl())
> &&
> + "given constructor for wrong type");
> MarkFunctionReferenced(ConstructLoc, Constructor);
> +
> return CXXConstructExpr::Create(
> Context, DeclInitType, ConstructLoc, Constructor, Elidable,
> ExprArgs, HadMultipleCandidates, IsListInitialization,
>
> Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaExceptionSpec.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Tue Jun 28 14:03:57 2016
> @@ -1001,6 +1001,10 @@ CanThrowResult Sema::canThrow(const Expr
> return mergeCanThrow(CT, canSubExprsThrow(*this, E));
> }
>
> + case Expr::CXXInheritedCtorInitExprClass:
> + return canCalleeThrow(*this, E,
> + cast<CXXInheritedCtorInitExpr>
> (E)->getConstructor());
> +
> case Expr::LambdaExprClass: {
> const LambdaExpr *Lambda = cast<LambdaExpr>(E);
> CanThrowResult CT = CT_Cannot;
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaExpr.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jun 28 14:03:57 2016
> @@ -221,21 +221,6 @@ void Sema::NoteDeletedFunction(FunctionD
> return;
> }
>
> - if (CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Decl)) {
> - if (CXXConstructorDecl *BaseCD =
> - const_cast<CXXConstructorDecl*>(CD->getInheritedConstructor()))
> {
> - Diag(Decl->getLocation(), diag::note_inherited_deleted_here);
> - if (BaseCD->isDeleted()) {
> - NoteDeletedFunction(BaseCD);
> - } else {
> - // FIXME: An explanation of why exactly it can't be inherited
> - // would be nice.
> - Diag(BaseCD->getLocation(), diag::note_cannot_inherit);
> - }
> - return;
> - }
> - }
> -
> Diag(Decl->getLocation(), diag::note_availability_specified_here)
> << Decl << true;
> }
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaExprCXX.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Jun 28 14:03:57 2016
> @@ -3186,9 +3186,8 @@ static ExprResult BuildCXXCastArgument(S
> if (S.CompleteConstructorCall(Constructor, From, CastLoc,
> ConstructorArgs))
> return ExprError();
>
> - S.CheckConstructorAccess(CastLoc, Constructor,
> - InitializedEntity::InitializeTemporary(Ty),
> - Constructor->getAccess());
> + S.CheckConstructorAccess(CastLoc, Constructor, FoundDecl,
> + InitializedEntity::InitializeTemporary(Ty));
> if (S.DiagnoseUseOfDecl(Method, CastLoc))
> return ExprError();
>
>
> Modified: cfe/trunk/lib/Sema/SemaInit.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaInit.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaInit.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Jun 28 14:03:57 2016
> @@ -5519,8 +5519,8 @@ static ExprResult CopyObject(Sema &S,
> SmallVector<Expr*, 8> ConstructorArgs;
> CurInit.get(); // Ownership transferred into MultiExprArg, below.
>
> - S.CheckConstructorAccess(Loc, Constructor, Entity,
> - Best->FoundDecl.getAccess(), IsExtraneousCopy);
> + S.CheckConstructorAccess(Loc, Constructor, Best->FoundDecl, Entity,
> + IsExtraneousCopy);
>
> if (IsExtraneousCopy) {
> // If this is a totally extraneous copy for C++03 reference
> @@ -5603,7 +5603,7 @@ static void CheckCXX98CompatAccessibleCo
> switch (OR) {
> case OR_Success:
> S.CheckConstructorAccess(Loc, cast<CXXConstructorDecl>(Best-
> >Function),
> - Entity, Best->FoundDecl.getAccess(), Diag);
> + Best->FoundDecl, Entity, Diag);
> // FIXME: Check default arguments as far as that's possible.
> break;
>
> @@ -5729,7 +5729,6 @@ PerformConstructorInitialization(Sema &S
>
> if (isExplicitTemporary(Entity, Kind, NumArgs)) {
> // An explicitly-constructed temporary, e.g., X(1, 2).
> - S.MarkFunctionReferenced(Loc, Constructor);
> if (S.DiagnoseUseOfDecl(Constructor, Loc))
> return ExprError();
>
> @@ -5741,6 +5740,11 @@ PerformConstructorInitialization(Sema &S
> ? SourceRange(LBraceLoc, RBraceLoc)
> : Kind.getParenRange();
>
> + if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(
> + Step.Function.FoundDecl.getDecl()))
> + Constructor = S.findInheritingConstructor(Loc, Constructor,
> Shadow);
> + S.MarkFunctionReferenced(Loc, Constructor);
> +
> CurInit = new (S.Context) CXXTemporaryObjectExpr(
> S.Context, Constructor, TSInfo,
> ConstructorArgs, ParenOrBraceRange, HadMultipleCandidates,
> @@ -5795,8 +5799,7 @@ PerformConstructorInitialization(Sema &S
> return ExprError();
>
> // Only check access if all of that succeeded.
> - S.CheckConstructorAccess(Loc, Constructor, Entity,
> - Step.Function.FoundDecl.getAccess());
> + S.CheckConstructorAccess(Loc, Constructor, Step.Function.FoundDecl,
> Entity);
> if (S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc))
> return ExprError();
>
> @@ -6529,8 +6532,8 @@ InitializationSequence::Perform(Sema &S,
> if (CurInit.isInvalid())
> return ExprError();
>
> - S.CheckConstructorAccess(Kind.getLocation(), Constructor, Entity,
> - FoundFn.getAccess());
> + S.CheckConstructorAccess(Kind.getLocation(), Constructor,
> FoundFn,
> + Entity);
> if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()))
> return ExprError();
>
> @@ -7296,13 +7299,16 @@ bool InitializationSequence::Diagnose(Se
> // initialize this base/member.
> CXXConstructorDecl *Constructor
> = cast<CXXConstructorDecl>(S.CurContext);
> + const CXXRecordDecl *InheritedFrom = nullptr;
> + if (auto Inherited = Constructor->getInheritedConstructor())
> + InheritedFrom = Inherited.getShadowDecl()->
> getNominatedBaseClass();
> if (Entity.getKind() == InitializedEntity::EK_Base) {
> S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
> - << (Constructor->getInheritedConstructor() ? 2 :
> - Constructor->isImplicit() ? 1 : 0)
> + << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0)
> << S.Context.getTypeDeclType(Constructor->getParent())
> << /*base=*/0
> - << Entity.getType();
> + << Entity.getType()
> + << InheritedFrom;
>
> RecordDecl *BaseDecl
> = Entity.getBaseSpecifier()->getType()->getAs<RecordType>()
> @@ -7311,11 +7317,11 @@ bool InitializationSequence::Diagnose(Se
> << S.Context.getTagDeclType(BaseDecl);
> } else {
> S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
> - << (Constructor->getInheritedConstructor() ? 2 :
> - Constructor->isImplicit() ? 1 : 0)
> + << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0)
> << S.Context.getTypeDeclType(Constructor->getParent())
> << /*member=*/1
> - << Entity.getName();
> + << Entity.getName()
> + << InheritedFrom;
> S.Diag(Entity.getDecl()->getLocation(),
> diag::note_member_declared_at);
>
>
> Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaLookup.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaLookup.cpp Tue Jun 28 14:03:57 2016
> @@ -2943,42 +2943,38 @@ Sema::SpecialMemberOverloadResult *Sema:
> // from an external source and invalidate lookup_result.
> SmallVector<NamedDecl *, 8> Candidates(R.begin(), R.end());
>
> - for (auto *Cand : Candidates) {
> - if (Cand->isInvalidDecl())
> + for (NamedDecl *CandDecl : Candidates) {
> + if (CandDecl->isInvalidDecl())
> continue;
>
> - if (UsingShadowDecl *U = dyn_cast<UsingShadowDecl>(Cand)) {
> - // FIXME: [namespace.udecl]p15 says that we should only consider a
> - // using declaration here if it does not match a declaration in the
> - // derived class. We do not implement this correctly in other cases
> - // either.
> - Cand = U->getTargetDecl();
> -
> - if (Cand->isInvalidDecl())
> - continue;
> - }
> -
> - if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(Cand)) {
> + DeclAccessPair Cand = DeclAccessPair::make(CandDecl, AS_public);
> + auto CtorInfo = getConstructorInfo(Cand);
> + if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(Cand->getUnderlyingDecl()))
> {
> if (SM == CXXCopyAssignment || SM == CXXMoveAssignment)
> - AddMethodCandidate(M, DeclAccessPair::make(M, AS_public), RD,
> ThisTy,
> - Classification, llvm::makeArrayRef(&Arg,
> NumArgs),
> - OCS, true);
> - else
> - AddOverloadCandidate(M, DeclAccessPair::make(M, AS_public),
> + AddMethodCandidate(M, Cand, RD, ThisTy, Classification,
> + llvm::makeArrayRef(&Arg, NumArgs), OCS, true);
> + else if (CtorInfo)
> + AddOverloadCandidate(CtorInfo.Constructor, CtorInfo.FoundDecl,
> llvm::makeArrayRef(&Arg, NumArgs), OCS,
> true);
> + else
> + AddOverloadCandidate(M, Cand, llvm::makeArrayRef(&Arg, NumArgs),
> OCS,
> + true);
> } else if (FunctionTemplateDecl *Tmpl =
> - dyn_cast<FunctionTemplateDecl>(Cand)) {
> + dyn_cast<FunctionTemplateDecl>(Cand->getUnderlyingDecl()))
> {
> if (SM == CXXCopyAssignment || SM == CXXMoveAssignment)
> - AddMethodTemplateCandidate(Tmpl, DeclAccessPair::make(Tmpl,
> AS_public),
> - RD, nullptr, ThisTy, Classification,
> - llvm::makeArrayRef(&Arg, NumArgs),
> - OCS, true);
> + AddMethodTemplateCandidate(
> + Tmpl, Cand, RD, nullptr, ThisTy, Classification,
> + llvm::makeArrayRef(&Arg, NumArgs), OCS, true);
> + else if (CtorInfo)
> + AddTemplateOverloadCandidate(
> + CtorInfo.ConstructorTmpl, CtorInfo.FoundDecl, nullptr,
> + llvm::makeArrayRef(&Arg, NumArgs), OCS, true);
> else
> - AddTemplateOverloadCandidate(Tmpl, DeclAccessPair::make(Tmpl,
> AS_public),
> - nullptr, llvm::makeArrayRef(&Arg,
> NumArgs),
> - OCS, true);
> + AddTemplateOverloadCandidate(
> + Tmpl, Cand, nullptr, llvm::makeArrayRef(&Arg, NumArgs), OCS,
> true);
> } else {
> - assert(isa<UsingDecl>(Cand) && "illegal Kind of operator = Decl");
> + assert(isa<UsingDecl>(Cand.getDecl()) &&
> + "illegal Kind of operator = Decl");
> }
> }
>
>
> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaOverload.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Jun 28 14:03:57 2016
> @@ -3055,7 +3055,7 @@ IsInitializerListConstructorConversion(S
> bool AllowExplicit) {
> for (auto *D : S.LookupConstructors(To)) {
> auto Info = getConstructorInfo(D);
> - if (!Info.Constructor)
> + if (!Info)
> continue;
>
> bool Usable = !Info.Constructor->isInvalidDecl() &&
> @@ -3174,7 +3174,7 @@ IsUserDefinedConversion(Sema &S, Expr *F
>
> for (auto *D : S.LookupConstructors(ToRecordDecl)) {
> auto Info = getConstructorInfo(D);
> - if (!Info.Constructor)
> + if (!Info)
> continue;
>
> bool Usable = !Info.Constructor->isInvalidDecl();
> @@ -8646,6 +8646,25 @@ bool clang::isBetterOverloadCandidate(Se
> return BetterTemplate == Cand1.Function->getPrimaryTemplate();
> }
>
> + // FIXME: Work around a defect in the C++17 inheriting constructor
> wording.
> + // A derived-class constructor beats an (inherited) base class
> constructor.
> + bool Cand1IsInherited =
> + dyn_cast_or_null<ConstructorUsingShadowDecl>(
> Cand1.FoundDecl.getDecl());
> + bool Cand2IsInherited =
> + dyn_cast_or_null<ConstructorUsingShadowDecl>(
> Cand2.FoundDecl.getDecl());
> + if (Cand1IsInherited != Cand2IsInherited)
> + return Cand2IsInherited;
> + else if (Cand1IsInherited) {
> + assert(Cand2IsInherited);
> + auto *Cand1Class = cast<CXXRecordDecl>(Cand1.
> Function->getDeclContext());
> + auto *Cand2Class = cast<CXXRecordDecl>(Cand2.
> Function->getDeclContext());
> + if (Cand1Class->isDerivedFrom(Cand2Class))
> + return true;
> + if (Cand2Class->isDerivedFrom(Cand1Class))
> + return false;
> + // Inherited from sibling base classes: still ambiguous.
> + }
> +
> // Check for enable_if value-based overload resolution.
> if (Cand1.Function && Cand2.Function) {
> Comparison Cmp = compareEnableIfAttrs(S, Cand1.Function,
> Cand2.Function);
> @@ -8837,7 +8856,8 @@ enum OverloadCandidateKind {
> oc_implicit_move_constructor,
> oc_implicit_copy_assignment,
> oc_implicit_move_assignment,
> - oc_implicit_inherited_constructor
> + oc_inherited_constructor,
> + oc_inherited_constructor_template
> };
>
> OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
> @@ -8853,11 +8873,13 @@ OverloadCandidateKind ClassifyOverloadCa
> }
>
> if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) {
> - if (!Ctor->isImplicit())
> - return isTemplate ? oc_constructor_template : oc_constructor;
> -
> - if (Ctor->getInheritedConstructor())
> - return oc_implicit_inherited_constructor;
> + if (!Ctor->isImplicit()) {
> + if (isa<ConstructorUsingShadowDecl>(Found))
> + return isTemplate ? oc_inherited_constructor_template
> + : oc_inherited_constructor;
> + else
> + return isTemplate ? oc_constructor_template : oc_constructor;
> + }
>
> if (Ctor->isDefaultConstructor())
> return oc_implicit_default_constructor;
> @@ -8889,14 +8911,13 @@ OverloadCandidateKind ClassifyOverloadCa
> return isTemplate ? oc_function_template : oc_function;
> }
>
> -void MaybeEmitInheritedConstructorNote(Sema &S, Decl *Fn) {
> - const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn);
> - if (!Ctor) return;
> -
> - Ctor = Ctor->getInheritedConstructor();
> - if (!Ctor) return;
> -
> - S.Diag(Ctor->getLocation(), diag::note_ovl_candidate_
> inherited_constructor);
> +void MaybeEmitInheritedConstructorNote(Sema &S, Decl *FoundDecl) {
> + // FIXME: It'd be nice to only emit a note once per using-decl per
> overload
> + // set.
> + if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl))
> + S.Diag(FoundDecl->getLocation(),
> + diag::note_ovl_candidate_inherited_constructor)
> + << Shadow->getNominatedBaseClass();
> }
>
> } // end anonymous namespace
> @@ -8982,7 +9003,7 @@ void Sema::NoteOverloadCandidate(NamedDe
>
> HandleFunctionTypeMismatch(PD, Fn->getType(), DestType);
> Diag(Fn->getLocation(), PD);
> - MaybeEmitInheritedConstructorNote(*this, Fn);
> + MaybeEmitInheritedConstructorNote(*this, Found);
> }
>
> // Notes the location of all overload candidates designated through
> @@ -9070,7 +9091,7 @@ static void DiagnoseBadConversion(Sema &
> << (unsigned) FnKind << FnDesc
> << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
> << ToTy << Name << I+1;
> - MaybeEmitInheritedConstructorNote(S, Fn);
> + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
> return;
> }
>
> @@ -9101,7 +9122,7 @@ static void DiagnoseBadConversion(Sema &
> << FromTy
> << FromQs.getAddressSpace() << ToQs.getAddressSpace()
> << (unsigned) isObjectArgument << I+1;
> - MaybeEmitInheritedConstructorNote(S, Fn);
> + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
> return;
> }
>
> @@ -9112,7 +9133,7 @@ static void DiagnoseBadConversion(Sema &
> << FromTy
> << FromQs.getObjCLifetime() << ToQs.getObjCLifetime()
> << (unsigned) isObjectArgument << I+1;
> - MaybeEmitInheritedConstructorNote(S, Fn);
> + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
> return;
> }
>
> @@ -9123,7 +9144,7 @@ static void DiagnoseBadConversion(Sema &
> << FromTy
> << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr()
> << (unsigned) isObjectArgument << I+1;
> - MaybeEmitInheritedConstructorNote(S, Fn);
> + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
> return;
> }
>
> @@ -9132,7 +9153,7 @@ static void DiagnoseBadConversion(Sema &
> << (unsigned) FnKind << FnDesc
> << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
> << FromTy << FromQs.hasUnaligned() << I+1;
> - MaybeEmitInheritedConstructorNote(S, Fn);
> + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
> return;
> }
>
> @@ -9150,7 +9171,7 @@ static void DiagnoseBadConversion(Sema &
> << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
> << FromTy << (CVR - 1) << I+1;
> }
> - MaybeEmitInheritedConstructorNote(S, Fn);
> + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
> return;
> }
>
> @@ -9161,7 +9182,7 @@ static void DiagnoseBadConversion(Sema &
> << (unsigned) FnKind << FnDesc
> << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
> << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
> - MaybeEmitInheritedConstructorNote(S, Fn);
> + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
> return;
> }
>
> @@ -9179,7 +9200,7 @@ static void DiagnoseBadConversion(Sema &
> << FromTy << ToTy << (unsigned) isObjectArgument << I+1
> << (unsigned) (Cand->Fix.Kind);
>
> - MaybeEmitInheritedConstructorNote(S, Fn);
> + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
> return;
> }
>
> @@ -9218,7 +9239,7 @@ static void DiagnoseBadConversion(Sema &
> << (unsigned) FnKind << FnDesc
> << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
> << (unsigned) isObjectArgument << I + 1;
> - MaybeEmitInheritedConstructorNote(S, Fn);
> + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
> return;
> }
> }
> @@ -9230,7 +9251,7 @@ static void DiagnoseBadConversion(Sema &
> << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
> << (BaseToDerivedConversion - 1)
> << FromTy << ToTy << I+1;
> - MaybeEmitInheritedConstructorNote(S, Fn);
> + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
> return;
> }
>
> @@ -9243,7 +9264,7 @@ static void DiagnoseBadConversion(Sema &
> << (unsigned) FnKind << FnDesc
> << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
> << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
> - MaybeEmitInheritedConstructorNote(S, Fn);
> + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
> return;
> }
> }
> @@ -9265,7 +9286,7 @@ static void DiagnoseBadConversion(Sema &
> FDiag << *HI;
> S.Diag(Fn->getLocation(), FDiag);
>
> - MaybeEmitInheritedConstructorNote(S, Fn);
> + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
> }
>
> /// Additional arity mismatch diagnosis specific to a function overload
> @@ -9341,7 +9362,7 @@ static void DiagnoseArityMismatch(Sema &
> S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
> << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() !=
> nullptr)
> << mode << modeCount << NumFormalArgs;
> - MaybeEmitInheritedConstructorNote(S, Fn);
> + MaybeEmitInheritedConstructorNote(S, Found);
> }
>
> /// Arity mismatch diagnosis specific to a function overload candidate.
> @@ -9377,7 +9398,7 @@ static void DiagnoseBadDeduction(Sema &S
> S.Diag(Templated->getLocation(),
> diag::note_ovl_candidate_incomplete_deduction)
> << ParamD->getDeclName();
> - MaybeEmitInheritedConstructorNote(S, Templated);
> + MaybeEmitInheritedConstructorNote(S, Found);
> return;
> }
>
> @@ -9402,7 +9423,7 @@ static void DiagnoseBadDeduction(Sema &S
>
> S.Diag(Templated->getLocation(), diag::note_ovl_candidate_
> underqualified)
> << ParamD->getDeclName() << Arg << NonCanonParam;
> - MaybeEmitInheritedConstructorNote(S, Templated);
> + MaybeEmitInheritedConstructorNote(S, Found);
> return;
> }
>
> @@ -9421,7 +9442,7 @@ static void DiagnoseBadDeduction(Sema &S
> diag::note_ovl_candidate_inconsistent_deduction)
> << which << ParamD->getDeclName() <<
> *DeductionFailure.getFirstArg()
> << *DeductionFailure.getSecondArg();
> - MaybeEmitInheritedConstructorNote(S, Templated);
> + MaybeEmitInheritedConstructorNote(S, Found);
> return;
> }
>
> @@ -9444,7 +9465,7 @@ static void DiagnoseBadDeduction(Sema &S
> diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
> << (index + 1);
> }
> - MaybeEmitInheritedConstructorNote(S, Templated);
> + MaybeEmitInheritedConstructorNote(S, Found);
> return;
>
> case Sema::TDK_TooManyArguments:
> @@ -9455,7 +9476,7 @@ static void DiagnoseBadDeduction(Sema &S
> case Sema::TDK_InstantiationDepth:
> S.Diag(Templated->getLocation(),
> diag::note_ovl_candidate_instantiation_depth);
> - MaybeEmitInheritedConstructorNote(S, Templated);
> + MaybeEmitInheritedConstructorNote(S, Found);
> return;
>
> case Sema::TDK_SubstitutionFailure: {
> @@ -9493,7 +9514,7 @@ static void DiagnoseBadDeduction(Sema &S
> S.Diag(Templated->getLocation(),
> diag::note_ovl_candidate_substitution_failure)
> << TemplateArgString << SFINAEArgString << R;
> - MaybeEmitInheritedConstructorNote(S, Templated);
> + MaybeEmitInheritedConstructorNote(S, Found);
> return;
> }
>
> @@ -9565,7 +9586,7 @@ static void DiagnoseBadDeduction(Sema &S
> // note_ovl_candidate_bad_deduction, which is uselessly vague.
> case Sema::TDK_MiscellaneousDeductionFailure:
> S.Diag(Templated->getLocation(), diag::note_ovl_candidate_bad_
> deduction);
> - MaybeEmitInheritedConstructorNote(S, Templated);
> + MaybeEmitInheritedConstructorNote(S, Found);
> return;
> }
> }
> @@ -9676,7 +9697,7 @@ static void NoteFunctionCandidate(Sema &
> S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted)
> << FnKind << FnDesc
> << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0);
> - MaybeEmitInheritedConstructorNote(S, Fn);
> + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
> return;
> }
>
> @@ -9698,7 +9719,7 @@ static void NoteFunctionCandidate(Sema &
> case ovl_fail_illegal_constructor: {
> S.Diag(Fn->getLocation(), diag::note_ovl_candidate_
> illegal_constructor)
> << (Fn->getPrimaryTemplate() ? 1 : 0);
> - MaybeEmitInheritedConstructorNote(S, Fn);
> + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
> return;
> }
>
> @@ -9764,7 +9785,6 @@ static void NoteSurrogateCandidate(Sema
>
> S.Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand)
> << FnType;
> - MaybeEmitInheritedConstructorNote(S, Cand->Surrogate);
> }
>
> static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc,
> @@ -10531,9 +10551,10 @@ private:
> UnresolvedSetIterator Result = S.getMostSpecialized(
> MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates,
> SourceExpr->getLocStart(), S.PDiag(),
> - S.PDiag(diag::err_addr_ovl_ambiguous) << Matches[0]
> -
> .second->getDeclName(),
> - S.PDiag(diag::note_ovl_candidate) << (unsigned)oc_function_
> template,
> + S.PDiag(diag::err_addr_ovl_ambiguous)
> + << Matches[0].second->getDeclName(),
> + S.PDiag(diag::note_ovl_candidate)
> + << (unsigned)oc_function_template,
> Complain, TargetFunctionType);
>
> if (Result != MatchesCopy.end()) {
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaTemplateInstantiateDecl.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Jun 28
> 14:03:57 2016
> @@ -1843,36 +1843,6 @@ TemplateDeclInstantiator::VisitCXXMethod
> Constructor->isExplicit(),
> Constructor->isInlineSpecified(),
> false,
> Constructor->isConstexpr());
> -
> - // Claim that the instantiation of a constructor or constructor
> template
> - // inherits the same constructor that the template does.
> - if (CXXConstructorDecl *Inh = const_cast<CXXConstructorDecl *>(
> - Constructor->getInheritedConstructor())) {
> - // If we're instantiating a specialization of a function template,
> our
> - // "inherited constructor" will actually itself be a function
> template.
> - // Instantiate a declaration of it, too.
> - if (FunctionTemplate) {
> - assert(!TemplateParams && Inh->getDescribedFunctionTemplate() &&
> - !Inh->getParent()->isDependentContext() &&
> - "inheriting constructor template in dependent context?");
> - Sema::InstantiatingTemplate Inst(SemaRef,
> Constructor->getLocation(),
> - Inh);
> - if (Inst.isInvalid())
> - return nullptr;
> - Sema::ContextRAII SavedContext(SemaRef, Inh->getDeclContext());
> - LocalInstantiationScope LocalScope(SemaRef);
> -
> - // Use the same template arguments that we deduced for the
> inheriting
> - // constructor. There's no way they could be deduced differently.
> - MultiLevelTemplateArgumentList InheritedArgs;
> - InheritedArgs.addOuterTemplateArguments(
> TemplateArgs.getInnermost());
> - Inh = cast_or_null<CXXConstructorDecl>(
> - SemaRef.SubstDecl(Inh, Inh->getDeclContext(), InheritedArgs));
> - if (!Inh)
> - return nullptr;
> - }
> - cast<CXXConstructorDecl>(Method)->setInheritedConstructor(Inh);
> - }
> } else if (CXXDestructorDecl *Destructor =
> dyn_cast<CXXDestructorDecl>(D)) {
> Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
> StartLoc, NameInfo, T, TInfo,
> @@ -2398,9 +2368,14 @@ Decl *TemplateDeclInstantiator::VisitUsi
> if (!QualifierLoc)
> return nullptr;
>
> - // The name info is non-dependent, so no transformation
> - // is required.
> + // For an inheriting constructor declaration, the name of the using
> + // declaration is the name of a constructor in this class, not in the
> + // base class.
> DeclarationNameInfo NameInfo = D->getNameInfo();
> + if (NameInfo.getName().getNameKind() == DeclarationName::
> CXXConstructorName)
> + if (auto *RD = dyn_cast<CXXRecordDecl>(SemaRef.CurContext))
> + NameInfo.setName(SemaRef.Context.DeclarationNames.
> getCXXConstructorName(
> + SemaRef.Context.getCanonicalType(SemaRef.
> Context.getRecordType(RD))));
>
> // We only need to do redeclaration lookups if we're in a class
> // scope (in fact, it's not really even possible in non-class
> @@ -2443,18 +2418,23 @@ Decl *TemplateDeclInstantiator::VisitUsi
> if (NewUD->isInvalidDecl())
> return NewUD;
>
> - if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName)
> {
> + if (NameInfo.getName().getNameKind() == DeclarationName::
> CXXConstructorName)
> SemaRef.CheckInheritingConstructorUsingDecl(NewUD);
> - return NewUD;
> - }
>
> bool isFunctionScope = Owner->isFunctionOrMethod();
>
> // Process the shadow decls.
> for (auto *Shadow : D->shadows()) {
> + // FIXME: UsingShadowDecl doesn't preserve its immediate target, so
> + // reconstruct it in the case where it matters.
> + NamedDecl *OldTarget = Shadow->getTargetDecl();
> + if (auto *CUSD = dyn_cast<ConstructorUsingShadowDecl>(Shadow))
> + if (auto *BaseShadow = CUSD->getNominatedBaseClassShadowDecl())
> + OldTarget = BaseShadow;
> +
> NamedDecl *InstTarget =
> cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl(
> - Shadow->getLocation(), Shadow->getTargetDecl(),
> TemplateArgs));
> + Shadow->getLocation(), OldTarget, TemplateArgs));
> if (!InstTarget)
> return nullptr;
>
> @@ -2484,6 +2464,12 @@ Decl *TemplateDeclInstantiator::VisitUsi
> // Ignore these; we handle them in bulk when processing the UsingDecl.
> return nullptr;
> }
> +
> +Decl *TemplateDeclInstantiator::VisitConstructorUsingShadowDecl(
> + ConstructorUsingShadowDecl *D) {
> + // Ignore these; we handle them in bulk when processing the UsingDecl.
> + return nullptr;
> +}
>
> Decl * TemplateDeclInstantiator
> ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
>
> Modified: cfe/trunk/lib/Sema/TreeTransform.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> TreeTransform.h?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
> +++ cfe/trunk/lib/Sema/TreeTransform.h Tue Jun 28 14:03:57 2016
> @@ -2690,6 +2690,16 @@ public:
> ParenRange);
> }
>
> + /// \brief Build a new implicit construction via inherited constructor
> + /// expression.
> + ExprResult RebuildCXXInheritedCtorInitExpr(QualType T, SourceLocation
> Loc,
> + CXXConstructorDecl
> *Constructor,
> + bool ConstructsVBase,
> + bool InheritedFromVBase) {
> + return new (getSema().Context) CXXInheritedCtorInitExpr(
> + Loc, T, Constructor, ConstructsVBase, InheritedFromVBase);
> + }
> +
> /// \brief Build a new object-construction expression.
> ///
> /// By default, performs semantic analysis to build the new expression.
> @@ -9937,6 +9947,32 @@ TreeTransform<Derived>::TransformCXXCons
> E->getParenOrBraceRange());
> }
>
> +template<typename Derived>
> +ExprResult TreeTransform<Derived>::TransformCXXInheritedCtorInitExpr(
> + CXXInheritedCtorInitExpr *E) {
> + QualType T = getDerived().TransformType(E->getType());
> + if (T.isNull())
> + return ExprError();
> +
> + CXXConstructorDecl *Constructor = cast_or_null<CXXConstructorDecl>(
> + getDerived().TransformDecl(E->getLocStart(), E->getConstructor()));
> + if (!Constructor)
> + return ExprError();
> +
> + if (!getDerived().AlwaysRebuild() &&
> + T == E->getType() &&
> + Constructor == E->getConstructor()) {
> + // Mark the constructor as referenced.
> + // FIXME: Instantiation-specific
> + SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor);
> + return E;
> + }
> +
> + return getDerived().RebuildCXXInheritedCtorInitExpr(
> + T, E->getLocation(), Constructor,
> + E->constructsVBase(), E->inheritedFromVBase());
> +}
> +
> /// \brief Transform a C++ temporary-binding expression.
> ///
> /// Since CXXBindTemporaryExpr nodes are implicitly generated, we just
>
> Modified: cfe/trunk/lib/Serialization/ASTCommon.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/
> Serialization/ASTCommon.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Serialization/ASTCommon.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTCommon.cpp Tue Jun 28 14:03:57 2016
> @@ -258,6 +258,7 @@ bool serialization::isRedeclarableDeclKi
> case Decl::CXXDestructor:
> case Decl::CXXConversion:
> case Decl::UsingShadow:
> + case Decl::ConstructorUsingShadow:
> case Decl::Var:
> case Decl::FunctionTemplate:
> case Decl::ClassTemplate:
>
> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/
> Serialization/ASTReaderDecl.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Jun 28 14:03:57 2016
> @@ -324,6 +324,7 @@ namespace clang {
> void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
> void VisitUsingDecl(UsingDecl *D);
> void VisitUsingShadowDecl(UsingShadowDecl *D);
> + void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D);
> void VisitLinkageSpecDecl(LinkageSpecDecl *D);
> void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
> void VisitImportDecl(ImportDecl *D);
> @@ -1421,6 +1422,16 @@ void ASTDeclReader::VisitUsingShadowDecl
> mergeRedeclarable(D, Redecl);
> }
>
> +void ASTDeclReader::VisitConstructorUsingShadowDecl(
> + ConstructorUsingShadowDecl *D) {
> + VisitUsingShadowDecl(D);
> + D->NominatedBaseClassShadowDecl =
> + ReadDeclAs<ConstructorUsingShadowDecl>(Record, Idx);
> + D->ConstructedBaseClassShadowDecl =
> + ReadDeclAs<ConstructorUsingShadowDecl>(Record, Idx);
> + D->IsVirtual = Record[Idx++];
> +}
> +
> void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
> VisitNamedDecl(D);
> D->UsingLoc = ReadSourceLocation(Record, Idx);
> @@ -1768,11 +1779,17 @@ void ASTDeclReader::VisitCXXMethodDecl(C
> }
>
> void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
> + // We need the inherited constructor information to merge the
> declaration,
> + // so we have to read it before we call VisitCXXMethodDecl.
> + if (D->isInheritingConstructor()) {
> + auto *Shadow = ReadDeclAs<ConstructorUsingShadowDecl>(Record, Idx);
> + auto *Ctor = ReadDeclAs<CXXConstructorDecl>(Record, Idx);
> + *D->getTrailingObjects<InheritedConstructor>() =
> + InheritedConstructor(Shadow, Ctor);
> + }
> +
> VisitCXXMethodDecl(D);
>
> - if (auto *CD = ReadDeclAs<CXXConstructorDecl>(Record, Idx))
> - if (D->isCanonicalDecl())
> - D->setInheritedConstructor(CD->getCanonicalDecl());
> D->IsExplicitSpecified = Record[Idx++];
> }
>
> @@ -2663,6 +2680,13 @@ static bool isSameEntity(NamedDecl *X, N
> // functions, etc.
> if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) {
> FunctionDecl *FuncY = cast<FunctionDecl>(Y);
> + if (CXXConstructorDecl *CtorX = dyn_cast<CXXConstructorDecl>(X)) {
> + CXXConstructorDecl *CtorY = cast<CXXConstructorDecl>(Y);
> + if (CtorX->getInheritedConstructor() &&
> + !isSameEntity(CtorX->getInheritedConstructor().
> getConstructor(),
> + CtorY->getInheritedConstructor().
> getConstructor()))
> + return false;
> + }
> return (FuncX->getLinkageInternal() == FuncY->getLinkageInternal()) &&
> FuncX->getASTContext().hasSameType(FuncX->getType(),
> FuncY->getType());
> }
> @@ -3240,6 +3264,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID I
> case DECL_USING_SHADOW:
> D = UsingShadowDecl::CreateDeserialized(Context, ID);
> break;
> + case DECL_CONSTRUCTOR_USING_SHADOW:
> + D = ConstructorUsingShadowDecl::CreateDeserialized(Context, ID);
> + break;
> case DECL_USING_DIRECTIVE:
> D = UsingDirectiveDecl::CreateDeserialized(Context, ID);
> break;
> @@ -3256,7 +3283,10 @@ Decl *ASTReader::ReadDeclRecord(DeclID I
> D = CXXMethodDecl::CreateDeserialized(Context, ID);
> break;
> case DECL_CXX_CONSTRUCTOR:
> - D = CXXConstructorDecl::CreateDeserialized(Context, ID);
> + D = CXXConstructorDecl::CreateDeserialized(Context, ID, false);
> + break;
> + case DECL_CXX_INHERITED_CONSTRUCTOR:
> + D = CXXConstructorDecl::CreateDeserialized(Context, ID, true);
> break;
> case DECL_CXX_DESTRUCTOR:
> D = CXXDestructorDecl::CreateDeserialized(Context, ID);
>
> Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/
> Serialization/ASTReaderStmt.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Tue Jun 28 14:03:57 2016
> @@ -1250,6 +1250,14 @@ void ASTStmtReader::VisitCXXConstructExp
> E->ParenOrBraceRange = ReadSourceRange(Record, Idx);
> }
>
> +void ASTStmtReader::VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr
> *E) {
> + VisitExpr(E);
> + E->Constructor = ReadDeclAs<CXXConstructorDecl>(Record, Idx);
> + E->Loc = ReadSourceLocation(Record, Idx);
> + E->ConstructsVirtualBase = Record[Idx++];
> + E->InheritedFromVirtualBase = Record[Idx++];
> +}
> +
> void ASTStmtReader::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr
> *E) {
> VisitCXXConstructExpr(E);
> E->Type = GetTypeSourceInfo(Record, Idx);
> @@ -3407,6 +3415,10 @@ Stmt *ASTReader::ReadStmtFromStream(Modu
> S = new (Context) CXXConstructExpr(Empty);
> break;
>
> + case EXPR_CXX_INHERITED_CTOR_INIT:
> + S = new (Context) CXXInheritedCtorInitExpr(Empty);
> + break;
> +
> case EXPR_CXX_TEMPORARY_OBJECT:
> S = new (Context) CXXTemporaryObjectExpr(Empty);
> break;
>
> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/
> Serialization/ASTWriter.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Jun 28 14:03:57 2016
> @@ -1104,6 +1104,7 @@ void ASTWriter::WriteBlockInfoBlock() {
> RECORD(DECL_CXX_RECORD);
> RECORD(DECL_CXX_METHOD);
> RECORD(DECL_CXX_CONSTRUCTOR);
> + RECORD(DECL_CXX_INHERITED_CONSTRUCTOR);
> RECORD(DECL_CXX_DESTRUCTOR);
> RECORD(DECL_CXX_CONVERSION);
> RECORD(DECL_ACCESS_SPEC);
>
> Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/
> Serialization/ASTWriterDecl.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Tue Jun 28 14:03:57 2016
> @@ -107,6 +107,7 @@ namespace clang {
> void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
> void VisitUsingDecl(UsingDecl *D);
> void VisitUsingShadowDecl(UsingShadowDecl *D);
> + void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D);
> void VisitLinkageSpecDecl(LinkageSpecDecl *D);
> void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
> void VisitImportDecl(ImportDecl *D);
> @@ -1126,6 +1127,15 @@ void ASTDeclWriter::VisitUsingShadowDecl
> Code = serialization::DECL_USING_SHADOW;
> }
>
> +void ASTDeclWriter::VisitConstructorUsingShadowDecl(
> + ConstructorUsingShadowDecl *D) {
> + VisitUsingShadowDecl(D);
> + Record.AddDeclRef(D->NominatedBaseClassShadowDecl);
> + Record.AddDeclRef(D->ConstructedBaseClassShadowDecl);
> + Record.push_back(D->IsVirtual);
> + Code = serialization::DECL_CONSTRUCTOR_USING_SHADOW;
> +}
> +
> void ASTDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
> VisitNamedDecl(D);
> Record.AddSourceLocation(D->getUsingLoc());
> @@ -1211,12 +1221,21 @@ void ASTDeclWriter::VisitCXXMethodDecl(C
> }
>
> void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
> + if (auto Inherited = D->getInheritedConstructor()) {
> + Record.AddDeclRef(Inherited.getShadowDecl());
> + Record.AddDeclRef(Inherited.getConstructor());
> + Code = serialization::DECL_CXX_INHERITED_CONSTRUCTOR;
> + } else {
> + Code = serialization::DECL_CXX_CONSTRUCTOR;
> + }
> +
> VisitCXXMethodDecl(D);
>
> - Record.AddDeclRef(D->getInheritedConstructor());
> Record.push_back(D->IsExplicitSpecified);
>
> - Code = serialization::DECL_CXX_CONSTRUCTOR;
> + Code = D->isInheritingConstructor()
> + ? serialization::DECL_CXX_INHERITED_CONSTRUCTOR
> + : serialization::DECL_CXX_CONSTRUCTOR;
> }
>
> void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
>
> Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/
> Serialization/ASTWriterStmt.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Tue Jun 28 14:03:57 2016
> @@ -1218,6 +1218,15 @@ void ASTStmtWriter::VisitCXXConstructExp
> Code = serialization::EXPR_CXX_CONSTRUCT;
> }
>
> +void ASTStmtWriter::VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr
> *E) {
> + VisitExpr(E);
> + Record.AddDeclRef(E->getConstructor());
> + Record.AddSourceLocation(E->getLocation());
> + Record.push_back(E->constructsVBase());
> + Record.push_back(E->inheritedFromVBase());
> + Code = serialization::EXPR_CXX_INHERITED_CTOR_INIT;
> +}
> +
> void ASTStmtWriter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr
> *E) {
> VisitCXXConstructExpr(E);
> Record.AddTypeSourceInfo(E->getTypeSourceInfo());
>
> Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/
> StaticAnalyzer/Core/ExprEngine.cpp?rev=274049&r1=
> 274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Tue Jun 28 14:03:57
> 2016
> @@ -755,6 +755,7 @@ void ExprEngine::Visit(const Stmt *S, Ex
> // C++ and ARC stuff we don't support yet.
> case Expr::ObjCIndirectCopyRestoreExprClass:
> case Stmt::CXXDependentScopeMemberExprClass:
> + case Stmt::CXXInheritedCtorInitExprClass:
> case Stmt::CXXTryStmtClass:
> case Stmt::CXXTypeidExprClass:
> case Stmt::CXXUuidofExprClass:
>
> Modified: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.
> qual/class.qual/p2.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp?
> rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
> (original)
> +++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
> Tue Jun 28 14:03:57 2016
> @@ -53,16 +53,17 @@ namespace InhCtor {
> int n = b.T(); // expected-error {{'T' is a protected member of
> 'InhCtor::A'}}
> // expected-note at -15 {{declared protected here}}
>
> + // FIXME: EDG and GCC reject this too, but it's not clear why it would
> be
> + // ill-formed.
> template<typename T>
> struct S : T {
> - struct U : S {
> + struct U : S { // expected-note 6{{candidate}}
> using S::S;
> };
> using T::T;
> };
> -
> - S<A>::U ua(0);
> - S<B>::U ub(0);
> + S<A>::U ua(0); // expected-error {{no match}}
> + S<B>::U ub(0); // expected-error {{no match}}
>
> template<typename T>
> struct X : T {
>
> Modified: cfe/trunk/test/CXX/basic/basic.types/p10.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> basic/basic.types/p10.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/basic/basic.types/p10.cpp (original)
> +++ cfe/trunk/test/CXX/basic/basic.types/p10.cpp Tue Jun 28 14:03:57 2016
> @@ -141,3 +141,45 @@ constexpr int arb(int n) {
> }
> constexpr long Overflow[ // expected-error {{constexpr variable cannot
> have non-literal type 'long const[(1 << 30) << 2]'}}
> (1 << 30) << 2]{}; // expected-warning {{requires 34 bits to
> represent}}
> +
> +namespace inherited_ctor {
> + struct A { constexpr A(int); };
> + struct B : A {
> + B();
> + using A::A;
> + };
> + constexpr int f(B) { return 0; } // ok
> +
> + struct C { constexpr C(int); };
> + struct D : C { // expected-note {{because}}
> + D(int);
> + using C::C;
> + };
> + constexpr int f(D) { return 0; } // expected-error {{not a literal
> type}}
> +
> + // This one is a bit odd: F inherits E's default constructor, which is
> + // constexpr. Because F has a constructor of its own, it doesn't
> declare a
> + // default constructor hiding E's one.
> + struct E {};
> + struct F : E {
> + F(int);
> + using E::E;
> + };
> + constexpr int f(F) { return 0; }
> +
> + // FIXME: Is this really the right behavior? We presumably should be
> checking
> + // whether the inherited constructor would be a copy or move
> constructor for
> + // the derived class, not for the base class.
> + struct G { constexpr G(const G&); };
> + struct H : G { // expected-note {{because}}
> + using G::G;
> + };
> + constexpr int f(H) { return 0; } // expected-error {{not a literal
> type}}
> +
> + struct J;
> + struct I { constexpr I(const J&); };
> + struct J : I {
> + using I::I;
> + };
> + constexpr int f(J) { return 0; }
> +}
>
> Added: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p15.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> dcl.dcl/basic.namespace/namespace.udecl/p15.cpp?rev=274049&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p15.cpp
> (added)
> +++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p15.cpp
> Tue Jun 28 14:03:57 2016
> @@ -0,0 +1,81 @@
> +// RUN: %clang_cc1 -std=c++11 -verify %s
> +
> +struct B1 { // expected-note 2{{candidate}}
> + B1(int); // expected-note {{candidate}}
> +};
> +
> +struct B2 { // expected-note 2{{candidate}}
> + B2(int); // expected-note {{candidate}}
> +};
> +
> +struct D1 : B1, B2 { // expected-note 2{{candidate}}
> + using B1::B1; // expected-note 3{{inherited here}}
> + using B2::B2; // expected-note 3{{inherited here}}
> +};
> +D1 d1(0); // expected-error {{ambiguous}}
> +
> +struct D2 : B1, B2 {
> + using B1::B1;
> + using B2::B2;
> + D2(int);
> +};
> +D2 d2(0); // ok
> +
> +
> +// The emergent behavior of implicit special members is a bit odd when
> +// inheriting from multiple base classes.
> +namespace default_ctor {
> + struct C;
> + struct D;
> +
> + struct A { // expected-note 4{{candidate}}
> + A(); // expected-note {{candidate}}
> +
> + A(C &&); // expected-note {{candidate}}
> + C &operator=(C&&); // expected-note {{candidate}}
> +
> + A(D &&); // expected-note {{candidate}}
> + D &operator=(D&&); // expected-note {{candidate}}
> + };
> +
> + struct B { // expected-note 4{{candidate}}
> + B(); // expected-note {{candidate}}
> +
> + B(C &&); // expected-note {{candidate}}
> + C &operator=(C&&); // expected-note {{candidate}}
> +
> + B(D &&); // expected-note {{candidate}}
> + D &operator=(D&&); // expected-note {{candidate}}
> + };
> +
> + struct C : A, B {
> + using A::A;
> + using A::operator=;
> + using B::B;
> + using B::operator=;
> + };
> + struct D : A, B {
> + using A::A; // expected-note 5{{inherited here}}
> + using A::operator=;
> + using B::B; // expected-note 5{{inherited here}}
> + using B::operator=;
> +
> + D(int);
> + D(const D&); // expected-note {{candidate}}
> + D &operator=(const D&); // expected-note {{candidate}}
> + };
> +
> + C c;
> + void f(C c) {
> + C c2(static_cast<C&&>(c));
> + c = static_cast<C&&>(c);
> + }
> +
> + // D does not declare D(), D(D&&), nor operator=(D&&), so the base class
> + // versions are inherited.
> + D d; // expected-error {{ambiguous}}
> + void f(D d) {
> + D d2(static_cast<D&&>(d)); // expected-error {{ambiguous}}
> + d = static_cast<D&&>(d); // expected-error {{ambiguous}}
> + }
> +}
>
> Added: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p18.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> dcl.dcl/basic.namespace/namespace.udecl/p18.cpp?rev=274049&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p18.cpp
> (added)
> +++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p18.cpp
> Tue Jun 28 14:03:57 2016
> @@ -0,0 +1,77 @@
> +// RUN: %clang_cc1 -std=c++11 -verify %s
> +
> +struct Public {} public_;
> +struct Protected {} protected_;
> +struct Private {} private_;
> +
> +class A {
> +public:
> + A(Public);
> + void f(Public);
> +
> +protected:
> + A(Protected); // expected-note {{protected here}}
> + void f(Protected);
> +
> +private:
> + A(Private); // expected-note 4{{private here}}
> + void f(Private); // expected-note {{private here}}
> +
> + friend void Friend();
> +};
> +
> +class B : private A {
> + using A::A; // ok
> + using A::f; // expected-error {{private member}}
> +
> + void f() {
> + B a(public_);
> + B b(protected_);
> + B c(private_); // expected-error {{private}}
> + }
> +
> + B(Public p, int) : B(p) {}
> + B(Protected p, int) : B(p) {}
> + B(Private p, int) : B(p) {} // expected-error {{private}}
> +};
> +
> +class C : public B {
> + C(Public p) : B(p) {}
> + // There is no access check on the conversion from derived to base here;
> + // protected constructors of A act like protected constructors of B.
> + C(Protected p) : B(p) {}
> + C(Private p) : B(p) {} // expected-error {{private}}
> +};
> +
> +void Friend() {
> + // There is no access check on the conversion from derived to base here.
> + B a(public_);
> + B b(protected_);
> + B c(private_);
> +}
> +
> +void NonFriend() {
> + B a(public_);
> + B b(protected_); // expected-error {{protected}}
> + B c(private_); // expected-error {{private}}
> +}
> +
> +namespace ProtectedAccessFromMember {
> +namespace a {
> + struct ES {
> + private:
> + ES(const ES &) = delete;
> + protected:
> + ES(const char *);
> + };
> +}
> +namespace b {
> + struct DES : a::ES {
> + DES *f();
> + private:
> + using a::ES::ES;
> + };
> +}
> +b::DES *b::DES::f() { return new b::DES("foo"); }
> +
> +}
>
> Modified: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.
> udecl/p4.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> dcl.dcl/basic.namespace/namespace.udecl/p4.cpp?rev=
> 274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp
> (original)
> +++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp Tue
> Jun 28 14:03:57 2016
> @@ -1,4 +1,5 @@
> // RUN: %clang_cc1 -fsyntax-only -verify %s
> +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
>
> // C++03 [namespace.udecl]p4:
> // A using-declaration used as a member-declaration shall refer to a
> @@ -206,8 +207,33 @@ namespace test4 {
> using Unrelated::foo; // expected-error {{not a base class}}
> using C::foo; // legal in C++03
> using Subclass::foo; // legal in C++03
> +#if __cplusplus >= 201103L
> + // expected-error at -3 {{refers to its own class}}
> + // expected-error at -3 {{refers into 'Subclass::', which is not a base
> class}}
> +#endif
>
> - int bar(); //expected-note {{target of using declaration}}
> + int bar();
> +#if __cplusplus < 201103L
> + // expected-note at -2 {{target of using declaration}}
> +#endif
> using C::bar; // expected-error {{refers to its own class}}
> };
> }
> +
> +namespace test5 {
> + struct B;
> + struct A {
> + A(const B&);
> + B &operator=(const B&);
> + };
> + struct B : A {
> +#if __cplusplus >= 201103L
> + using A::A;
> +#endif
> + using A::operator=;
> + };
> + void test(B b) {
> + B b2(b);
> + b2 = b;
> + }
> +}
>
> Modified: cfe/trunk/test/CXX/drs/dr15xx.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> drs/dr15xx.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/drs/dr15xx.cpp (original)
> +++ cfe/trunk/test/CXX/drs/dr15xx.cpp Tue Jun 28 14:03:57 2016
> @@ -22,6 +22,31 @@ namespace dr1560 { // dr1560: 3.5
> const X &x = true ? get() : throw 0;
> }
>
> +namespace dr1573 { // dr1573: 3.9
> +#if __cplusplus >= 201103L
> + // ellipsis is inherited (p0136r1 supersedes this part).
> + struct A { A(); A(int, char, ...); };
> + struct B : A { using A::A; };
> + B b(1, 'x', 4.0, "hello"); // ok
> +
> + // inherited constructor is effectively constexpr if the user-written
> constructor would be
> + struct C { C(); constexpr C(int) {} };
> + struct D : C { using C::C; };
> + constexpr D d = D(0); // ok
> + struct E : C { using C::C; A a; }; // expected-note {{non-literal type}}
> + constexpr E e = E(0); // expected-error {{non-literal type}}
> + // FIXME: This diagnostic is pretty bad; we should explain that the
> problem
> + // is that F::c would be initialized by a non-constexpr constructor.
> + struct F : C { using C::C; C c; }; // expected-note {{here}}
> + constexpr F f = F(0); // expected-error {{constant expression}}
> expected-note {{constructor inherited from base class 'C'}}
> +
> + // inherited constructor is effectively deleted if the user-written
> constructor would be
> + struct G { G(int); }; // expected-note {{declared here}}
> + struct H : G { using G::G; G g; }; // expected-error {{cannot use
> constructor inherited from base class 'G'; member 'g' of 'dr1573::H' does
> not have a default constructor}} expected-note {{declared here}}
> + H h(0); // expected-note {{first required here}}
> +#endif
> +}
> +
> #if __cplusplus >= 201103L
> namespace std {
> typedef decltype(sizeof(int)) size_t;
>
> Modified: cfe/trunk/test/CXX/drs/dr16xx.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> drs/dr16xx.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/drs/dr16xx.cpp (original)
> +++ cfe/trunk/test/CXX/drs/dr16xx.cpp Tue Jun 28 14:03:57 2016
> @@ -18,8 +18,8 @@ namespace dr1684 { // dr1684: 3.6
> #endif
> }
>
> +namespace dr1631 { // dr1631: 3.7
> #if __cplusplus >= 201103L
> -namespace dr1631 { // dr1631: 3.7 c++11
> // Incorrect overload resolution for single-element initializer-list
>
> struct A { int a[1]; };
> @@ -41,5 +41,22 @@ namespace dr1631 { // dr1631: 3.7 c++11
> f({0}, {{1}}); // expected-error{{call to 'f' is ambiguous}}
> }
> }
> -} // dr1631
> #endif
> +}
> +
> +namespace dr1645 { // dr1645: 3.9
> +#if __cplusplus >= 201103L
> + struct A { // expected-note 2{{candidate}}
> + constexpr A(int, float = 0); // expected-note 2{{candidate}}
> + explicit A(int, int = 0); // expected-note 2{{candidate}}
> + A(int, int, int = 0) = delete; // expected-note {{candidate}}
> + };
> +
> + struct B : A { // expected-note 2{{candidate}}
> + using A::A; // expected-note 7{{inherited here}}
> + };
> +
> + constexpr B a(0); // expected-error {{ambiguous}}
> + constexpr B b(0, 0); // expected-error {{ambiguous}}
> +#endif
> +}
>
> Modified: cfe/trunk/test/CXX/drs/dr17xx.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> drs/dr17xx.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/drs/dr17xx.cpp (original)
> +++ cfe/trunk/test/CXX/drs/dr17xx.cpp Tue Jun 28 14:03:57 2016
> @@ -3,19 +3,63 @@
> // RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions
> -pedantic-errors
> // RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions
> -pedantic-errors
>
> +#if __cplusplus < 201103L
> // expected-no-diagnostics
> +#endif
>
> +namespace dr1715 { // dr1715: 3.9
> +#if __cplusplus >= 201103L
> + struct B {
> + template<class T> B(T, typename T::Q);
> + };
> +
> + class S {
> + using Q = int;
> + template<class T> friend B::B(T, typename T::Q);
> + };
> +
> + struct D : B {
> + using B::B;
> + };
> + struct E : B { // expected-note 2{{candidate}}
> + template<class T> E(T t, typename T::Q q) : B(t, q) {} //
> expected-note {{'Q' is a private member}}
> + };
> +
> + B b(S(), 1);
> + D d(S(), 2);
> + E e(S(), 3); // expected-error {{no match}}
> +#endif
> +}
> +
> +namespace dr1736 { // dr1736: 3.9
> +#if __cplusplus >= 201103L
> +struct S {
> + template <class T> S(T t) {
> + struct L : S {
> + using S::S;
> + };
> + typename T::type value; // expected-error {{no member}}
> + L l(value); // expected-note {{instantiation of}}
> + }
> +};
> +struct Q { typedef int type; } q;
> +S s(q); // expected-note {{instantiation of}}
> +#endif
> +}
> +
> +namespace dr1756 { // dr1756: 3.7
> #if __cplusplus >= 201103L
> -namespace dr1756 { // dr1756: 3.7 c++11
> // Direct-list-initialization of a non-class object
>
> int a{0};
>
> struct X { operator int(); } x;
> int b{x};
> -} // dr1756
> +#endif
> +}
>
> -namespace dr1758 { // dr1758: 3.7 c++11
> +namespace dr1758 { // dr1758: 3.7
> +#if __cplusplus >= 201103L
> // Explicit conversion in copy/move list initialization
>
> struct X { X(); };
> @@ -30,5 +74,5 @@ namespace dr1758 { // dr1758: 3.7 c++11
> operator A() { return A(); }
> } b;
> A a{b};
> -} // dr1758
> #endif
> +}
>
> Modified: cfe/trunk/test/CXX/drs/dr19xx.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> drs/dr19xx.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/drs/dr19xx.cpp (original)
> +++ cfe/trunk/test/CXX/drs/dr19xx.cpp Tue Jun 28 14:03:57 2016
> @@ -39,6 +39,31 @@ namespace dr1902 { // dr1902: 3.7
> #endif
> }
>
> +namespace dr1903 {
> + namespace A {
> + struct a {};
> + int a;
> + namespace B {
> + int b;
> + }
> + using namespace B;
> + namespace {
> + int c;
> + }
> + namespace D {
> + int d;
> + }
> + using D::d;
> + }
> + namespace X {
> + using A::a;
> + using A::b;
> + using A::c;
> + using A::d;
> + struct a *p;
> + }
> +}
> +
> namespace dr1909 { // dr1909: yes
> struct A {
> template<typename T> struct A {}; // expected-error {{member 'A' has
> the same name as its class}}
> @@ -54,22 +79,52 @@ namespace dr1909 { // dr1909: yes
> };
> }
>
> -#if __cplusplus >= 201103L
> namespace dr1940 { // dr1940: yes
> +#if __cplusplus >= 201103L
> static union {
> static_assert(true, ""); // ok
> static_assert(false, ""); // expected-error {{static_assert failed}}
> };
> -}
> #endif
> +}
>
> +namespace dr1941 { // dr1941: 3.9
> #if __cplusplus >= 201402L
> +template<typename X>
> +struct base {
> + template<typename T>
> + base(T a, T b, decltype(void(*T()), 0) = 0) {
> + while (a != b) (void)*a++;
> + }
> +
> + template<typename T>
> + base(T a, X x, decltype(void(T(0) * 1), 0) = 0) {
> + for (T n = 0; n != a; ++n) (void)X(x);
> + }
> +};
> +
> +struct derived : base<int> {
> + using base::base;
> +};
> +
> +struct iter {
> + iter operator++(int);
> + int operator*();
> + friend bool operator!=(iter, iter);
> +} it, end;
> +
> +derived d1(it, end);
> +derived d2(42, 9);
> +#endif
> +}
> +
> namespace dr1947 { // dr1947: yes
> +#if __cplusplus >= 201402L
> unsigned o = 0'01; // ok
> unsigned b = 0b'01; // expected-error {{invalid digit 'b' in octal
> constant}}
> unsigned x = 0x'01; // expected-error {{invalid suffix 'x'01' on integer
> constant}}
> -}
> #endif
> +}
>
> #if __cplusplus >= 201103L
> // dr1948: yes
> @@ -77,10 +132,58 @@ unsigned x = 0x'01; // expected-error {{
> void *operator new(__SIZE_TYPE__) noexcept { return nullptr; } //
> expected-error{{exception specification in declaration does not match
> previous declaration}}
> #endif
>
> +namespace dr1959 { // dr1959: 3.9
> #if __cplusplus >= 201103L
> + struct b;
> + struct c;
> + struct a {
> + a() = default;
> + a(const a &) = delete; // expected-note 2{{deleted}}
> + a(const b &) = delete; // not inherited
> + a(c &&) = delete; // expected-note {{deleted}}
> + template<typename T> a(T) = delete;
> + };
> +
> + struct b : a { // expected-note {{copy constructor of 'b' is implicitly
> deleted because base class 'dr1959::a' has a deleted copy constructor}}
> + using a::a;
> + };
> +
> + a x;
> + b y = x; // expected-error {{deleted}}
> + b z = z; // expected-error {{deleted}}
> +
> + // FIXME: It's not really clear that this matches the intent, but it's
> + // consistent with the behavior for assignment operators.
> + struct c : a {
> + using a::a;
> + c(const c &);
> + };
> + c q(static_cast<c&&>(q)); // expected-error {{call to deleted}}
> +#endif
> +}
> +
> namespace dr1968 { // dr1968: yes
> -static_assert(&typeid(int) == &typeid(int), ""); // expected-error{{not
> an integral constant expression}}
> +#if __cplusplus >= 201103L
> + static_assert(&typeid(int) == &typeid(int), ""); // expected-error{{not
> an integral constant expression}}
> +#endif
> }
> +
> +namespace dr1991 { // dr1991: 3.9
> +#if __cplusplus >= 201103L
> + struct A {
> + A(int, int) = delete;
> + };
> +
> + struct B : A {
> + using A::A;
> + B(int, int, int = 0);
> + };
> +
> + // FIXME: As a resolution to an open DR against P0136R1, we treat
> derived
> + // class constructors as better than base class constructors in the
> presence
> + // of ambiguity.
> + B b(0, 0); // ok, calls B constructor
> #endif
> +}
>
> // dr1994: dup 529
>
> Modified: cfe/trunk/test/CXX/except/except.spec/p14.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> except/except.spec/p14.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/except/except.spec/p14.cpp (original)
> +++ cfe/trunk/test/CXX/except/except.spec/p14.cpp Tue Jun 28 14:03:57 2016
> @@ -124,14 +124,20 @@ namespace InhCtor {
> template<typename T> struct Throw {
> Throw() throw(T);
> };
> - struct Derived : Base, Throw<X<3>> {
> + struct Derived1 : Base, X<5> {
> + using Base::Base;
> + int n;
> + };
> + struct Derived2 : Base, Throw<X<3>> {
> using Base::Base;
> - Throw<X<4>> x;
> };
> - struct Test {
> - friend Derived::Derived(X<0>) throw(X<3>, X<4>);
> - friend Derived::Derived(X<1>) noexcept(false);
> - friend Derived::Derived(X<2>) throw(X<2>, X<3>, X<4>);
> + struct Derived3 : Base {
> + using Base::Base;
> + Throw<X<4>> x;
> };
> - static_assert(!noexcept(Derived{X<5>{}}), "");
> + static_assert(noexcept(Derived1(X<0>())), "");
> + static_assert(!noexcept(Derived1(X<1>())), "");
> + static_assert(!noexcept(Derived1(X<2>())), "");
> + static_assert(!noexcept(Derived2(X<0>())), "");
> + static_assert(!noexcept(Derived3(X<0>())), "");
> }
>
> Modified: cfe/trunk/test/CXX/special/class.inhctor/p1.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> special/class.inhctor/p1.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/special/class.inhctor/p1.cpp (original)
> +++ cfe/trunk/test/CXX/special/class.inhctor/p1.cpp Tue Jun 28 14:03:57
> 2016
> @@ -1,53 +1,55 @@
> // RUN: %clang_cc1 -std=c++11 -verify %s
> -// Per a core issue (no number yet), an ellipsis is always dropped.
> -struct A {
> - A(...); // expected-note {{here}}
> - A(int = 0, int = 0, int = 0, int = 0, ...); // expected-note 9{{here}}
> expected-note 2{{constructor cannot be inherited}}
> - A(int = 0, int = 0, ...); // expected-note {{here}}
> +//
> +// Note: [class.inhctor] was removed by P0136R1. This tests the new
> behavior
> +// for the wording that used to be there.
> +
> +struct A { // expected-note 8{{candidate is the implicit}}
> + A(...); // expected-note 4{{candidate constructor}} expected-note
> 4{{candidate inherited constructor}}
> + A(int = 0, int = 0, int = 0, int = 0, ...); // expected-note
> 3{{candidate constructor}} expected-note 3{{candidate inherited
> constructor}}
> + A(int = 0, int = 0, ...); // expected-note 3{{candidate constructor}}
> expected-note 3{{candidate inherited constructor}}
>
> - template<typename T> A(T, int = 0, ...); // expected-note 5{{here}}
> + template<typename T> A(T, int = 0, ...); // expected-note 3{{candidate
> constructor}} expected-note 3{{candidate inherited constructor}}
>
> - template<typename T, int N> A(const T (&)[N]); // expected-note
> 2{{here}} expected-note {{constructor cannot be inherited}}
> - template<typename T, int N> A(const T (&)[N], int = 0); //
> expected-note 2{{here}}
> + template<typename T, int N> A(const T (&)[N]); // expected-note
> {{candidate constructor}} expected-note {{candidate inherited constructor}}
> + template<typename T, int N> A(const T (&)[N], int = 0); //
> expected-note {{candidate constructor}} expected-note {{candidate inherited
> constructor}}
> };
>
> -struct B : A { // expected-note 6{{candidate}}
> - using A::A; // expected-warning 4{{inheriting constructor does not
> inherit ellipsis}} expected-note 16{{candidate}} expected-note 3{{deleted
> constructor was inherited here}}
> +struct B : A { // expected-note 4{{candidate is the implicit}}
> + using A::A; // expected-note 19{{inherited here}}
> + B(void*);
> };
>
> struct C {} c;
>
> -B b0{};
> -// expected-error at -1 {{call to implicitly-deleted default constructor of
> 'B'}}
> -// expected-note at -8 {{default constructor of 'B' is implicitly deleted
> because base class 'A' has multiple default constructors}}
> +A a0{}; // expected-error {{ambiguous}}
> +B b0{}; // expected-error {{ambiguous}}
>
> -B b1{1};
> -// expected-error at -1 {{call to deleted constructor of 'B'}}
> +A a1{1}; // expected-error {{ambiguous}}
> +B b1{1}; // expected-error {{ambiguous}}
>
> -B b2{1,2};
> -// expected-error at -1 {{call to deleted constructor of 'B'}}
> +A a2{1,2}; // expected-error {{ambiguous}}
> +B b2{1,2}; // expected-error {{ambiguous}}
>
> -B b3{1,2,3};
> -// ok
> +A a3{1,2,3}; // ok
> +B b3{1,2,3}; // ok
>
> -B b4{1,2,3,4};
> -// ok
> +A a4{1,2,3,4}; // ok
> +B b4{1,2,3,4}; // ok
>
> -B b5{1,2,3,4,5};
> -// expected-error at -1 {{no matching constructor for initialization of
> 'B'}}
> +A a5{1,2,3,4,5}; // ok
> +B b5{1,2,3,4,5}; // ok
>
> -B b6{c};
> -// ok
> +A a6{c}; // ok
> +B b6{c}; // ok
>
> -B b7{c,0};
> -// ok
> +A a7{c,0}; // ok
> +B b7{c,0}; // ok
>
> -B b8{c,0,1};
> -// expected-error at -1 {{no matching constructor}}
> +A a8{c,0,1}; // ok
> +B b8{c,0,1}; // ok
>
> -B b9{"foo"};
> -// FIXME: explain why the inheriting constructor was deleted
> -// expected-error at -2 {{call to deleted constructor of 'B'}}
> +A a9{"foo"}; // expected-error {{ambiguous}}
> +B b9{"foo"}; // expected-error {{ambiguous}}
>
> namespace PR15755 {
> struct X {
>
> Modified: cfe/trunk/test/CXX/special/class.inhctor/p2.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> special/class.inhctor/p2.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/special/class.inhctor/p2.cpp (original)
> +++ cfe/trunk/test/CXX/special/class.inhctor/p2.cpp Tue Jun 28 14:03:57
> 2016
> @@ -1,4 +1,7 @@
> // RUN: %clang_cc1 -std=c++11 -verify %s
> +//
> +// Note: [class.inhctor] was removed by P0136R1. This tests the new
> behavior
> +// for the wording that used to be there.
>
> template<int> struct X {};
>
> @@ -8,10 +11,10 @@ template<int> struct X {};
> // - absence or presence of explicit
> // - absence or presence of constexpr
> struct A {
> - A(X<0>) {} // expected-note 2{{here}}
> + A(X<0>) {} // expected-note 4{{here}}
> constexpr A(X<1>) {}
> - explicit A(X<2>) {} // expected-note 3{{here}}
> - explicit constexpr A(X<3>) {} // expected-note 2{{here}}
> + explicit A(X<2>) {} // expected-note 6{{here}}
> + explicit constexpr A(X<3>) {} // expected-note 4{{here}}
> };
>
> A a0 { X<0>{} };
> @@ -36,7 +39,7 @@ constexpr A a3ic = { X<3>{} }; // expect
>
>
> struct B : A {
> - using A::A; // expected-note 7{{here}}
> + using A::A;
> };
>
> B b0 { X<0>{} };
> @@ -62,14 +65,19 @@ constexpr B b3ic = { X<3>{} }; // expect
>
> // 'constexpr' is OK even if the constructor doesn't obey the constraints.
> struct NonLiteral { NonLiteral(); };
> -struct NonConstexpr { NonConstexpr(); constexpr NonConstexpr(int); }; //
> expected-note {{here}}
> +struct NonConstexpr { NonConstexpr(); constexpr NonConstexpr(int); };
> struct Constexpr { constexpr Constexpr(int) {} };
>
> struct BothNonLiteral : NonLiteral, Constexpr { using
> Constexpr::Constexpr; }; // expected-note {{base class 'NonLiteral' of
> non-literal type}}
> constexpr BothNonLiteral bothNL{42}; // expected-error {{constexpr
> variable cannot have non-literal type 'const BothNonLiteral'}}
>
> -struct BothNonConstexpr : NonConstexpr, Constexpr { using
> Constexpr::Constexpr; }; // expected-note {{non-constexpr constructor
> 'NonConstexpr}}
> -constexpr BothNonConstexpr bothNC{42}; // expected-error {{must be
> initialized by a constant expression}} expected-note {{in call to
> 'BothNonConstexpr(42)'}}
> +// FIXME: This diagnostic is not very good. We should explain that the
> problem is that base class NonConstexpr cannot be initialized.
> +struct BothNonConstexpr
> + : NonConstexpr,
> + Constexpr {
> + using Constexpr::Constexpr; // expected-note {{here}}
> +};
> +constexpr BothNonConstexpr bothNC{42}; // expected-error {{must be
> initialized by a constant expression}} expected-note {{inherited from base
> class 'Constexpr'}}
>
>
> struct ConstexprEval {
> @@ -87,25 +95,25 @@ static_assert(ce.k == 'a', "");
> static_assert(ce.k2 == 'x', "");
>
>
> -struct TemplateCtors {
> - constexpr TemplateCtors() {}
> - template<template<int> class T> TemplateCtors(X<0>, T<0>);
> - template<int N> TemplateCtors(X<1>, X<N>);
> - template<typename T> TemplateCtors(X<2>, T);
> +struct TemplateCtors { // expected-note 2{{candidate constructor (the
> implicit}}
> + constexpr TemplateCtors() {} // expected-note {{candidate inherited
> constructor}}
> + template<template<int> class T> TemplateCtors(X<0>, T<0>); //
> expected-note {{here}} expected-note {{candidate inherited constructor}}
> + template<int N> TemplateCtors(X<1>, X<N>); // expected-note {{here}}
> expected-note {{candidate inherited constructor}}
> + template<typename T> TemplateCtors(X<2>, T); // expected-note {{here}}
> expected-note {{candidate inherited constructor}}
>
> - template<typename T = int> TemplateCtors(int, int = 0, int = 0); //
> expected-note {{inherited from here}}
> + template<typename T = int> TemplateCtors(int, int = 0, int = 0);
> };
>
> -struct UsingTemplateCtors : TemplateCtors { // expected-note
> 2{{candidate is the implicit}}
> - using TemplateCtors::TemplateCtors; // expected-note 4{{here}}
> expected-note {{candidate}}
> +struct UsingTemplateCtors : TemplateCtors { // expected-note 2{{candidate
> constructor (the implicit}}
> + using TemplateCtors::TemplateCtors; // expected-note 6{{inherited here}}
>
> - constexpr UsingTemplateCtors(X<0>, X<0>) {}
> - constexpr UsingTemplateCtors(X<1>, X<1>) {}
> - constexpr UsingTemplateCtors(X<2>, X<2>) {}
> + constexpr UsingTemplateCtors(X<0>, X<0>) {} // expected-note {{not
> viable}}
> + constexpr UsingTemplateCtors(X<1>, X<1>) {} // expected-note {{not
> viable}}
> + constexpr UsingTemplateCtors(X<2>, X<2>) {} // expected-note {{not
> viable}}
>
> - template<int = 0> constexpr UsingTemplateCtors(int) {} // expected-note
> {{candidate}}
> - template<typename T = void> constexpr UsingTemplateCtors(int, int) {}
> - template<typename T, typename U> constexpr UsingTemplateCtors(int, int,
> int) {}
> + template<int = 0> constexpr UsingTemplateCtors(int) {} // expected-note
> {{not viable}}
> + template<typename T = void> constexpr UsingTemplateCtors(int, int) {}
> // expected-note {{not viable}}
> + template<typename T, typename U> constexpr UsingTemplateCtors(int, int,
> int) {} // expected-note {{couldn't infer}}
> };
>
> template<int> struct Y {};
> @@ -116,6 +124,10 @@ constexpr UsingTemplateCtors uct4{ X<1>{
> constexpr UsingTemplateCtors uct5{ X<2>{}, 0 }; // expected-error {{must
> be initialized by a constant expression}} expected-note {{non-constexpr}}
> constexpr UsingTemplateCtors uct6{ X<2>{}, X<2>{} };
>
> -constexpr UsingTemplateCtors utc7{ 0 }; // expected-error {{ambiguous}}
> +constexpr UsingTemplateCtors utc7{ 0 }; // ok
> constexpr UsingTemplateCtors utc8{ 0, 0 }; // ok
> -constexpr UsingTemplateCtors utc9{ 0, 0, 0 }; // expected-error {{must be
> initialized by a constant expression}} expected-note {{non-constexpr}}
> +// FIXME: The standard says that UsingTemplateCtors' (int, int, int)
> constructor
> +// hides the one from TemplateCtors, even though the template parameter
> lists
> +// don't match. It's not clear that that's *really* the intent, and it's
> not
> +// what other compilers do.
> +constexpr UsingTemplateCtors utc9{ 0, 0, 0 }; // expected-error {{no
> matching constructor}}
>
> Modified: cfe/trunk/test/CXX/special/class.inhctor/p3.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> special/class.inhctor/p3.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/special/class.inhctor/p3.cpp (original)
> +++ cfe/trunk/test/CXX/special/class.inhctor/p3.cpp Tue Jun 28 14:03:57
> 2016
> @@ -1,8 +1,11 @@
> // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
> +//
> +// Note: [class.inhctor] was removed by P0136R1. This tests the new
> behavior
> +// for the wording that used to be there.
>
> struct B1 {
> - B1(int);
> - B1(int, int);
> + B1(int); // expected-note 3{{target of using}}
> + B1(int, int); // expected-note 3{{target of using}}
> };
> struct D1 : B1 {
> using B1::B1;
> @@ -11,48 +14,56 @@ D1 d1a(1), d1b(1, 1);
>
> D1 fd1() { return 1; }
>
> -struct B2 {
> +struct B2 { // expected-note 2{{candidate}}
> explicit B2(int, int = 0, int = 0);
> };
> -struct D2 : B2 { // expected-note 2 {{candidate constructor}}
> - using B2::B2;
> +struct D2 : B2 { // expected-note 2{{candidate constructor}}
> + using B2::B2; // expected-note 2{{inherited here}}
> };
> D2 d2a(1), d2b(1, 1), d2c(1, 1, 1);
>
> D2 fd2() { return 1; } // expected-error {{no viable conversion}}
>
> -struct B3 {
> - B3(void*); // expected-note {{inherited from here}}
> +struct B3 { // expected-note 2{{candidate}}
> + B3(void*); // expected-note {{candidate}}
> };
> -struct D3 : B3 { // expected-note 2 {{candidate constructor}}
> - using B3::B3; // expected-note {{candidate constructor (inherited)}}
> +struct D3 : B3 { // expected-note 2{{candidate constructor}}
> + using B3::B3; // expected-note 3{{inherited here}}
> };
> D3 fd3() { return 1; } // expected-error {{no viable conversion}}
>
> template<typename T> struct T1 : B1 {
> - using B1::B1;
> + using B1::B1; // expected-note 2{{using declaration}}
> };
> template<typename T> struct T2 : T1<T> {
> - using T1<int>::T1;
> + using T1<int>::T1; // expected-note 2{{using declaration}}
> };
> template<typename T> struct T3 : T1<int> {
> - using T1<T>::T1;
> + using T1<T>::T1; // expected-note 2{{using declaration}}
> };
> struct U {
> - friend T1<int>::T1(int);
> - friend T1<int>::T1(int, int);
> - friend T2<int>::T2(int);
> - friend T2<int>::T2(int, int);
> - friend T3<int>::T3(int);
> - friend T3<int>::T3(int, int);
> + // [dcl.meaning]p1: "the member shall not merely hav ebeen introduced
> by a
> + // using-declaration in the scope of the class [...] nominated by the
> + // nested-name-specifier of the declarator-id"
> + friend T1<int>::T1(int); // expected-error {{cannot befriend target of
> using declaration}}
> + friend T1<int>::T1(int, int); // expected-error {{cannot befriend
> target of using declaration}}
> + friend T2<int>::T2(int); // expected-error {{cannot befriend target of
> using declaration}}
> + friend T2<int>::T2(int, int); // expected-error {{cannot befriend
> target of using declaration}}
> + friend T3<int>::T3(int); // expected-error {{cannot befriend target of
> using declaration}}
> + friend T3<int>::T3(int, int); // expected-error {{cannot befriend
> target of using declaration}}
> };
>
> struct B4 {
> - template<typename T> explicit B4(T, int = 0);
> + template<typename T> explicit B4(T, int = 0); // expected-note 2{{here}}
> };
> template<typename T> struct T4 : B4 {
> - using B4::B4; // expected-note {{here}}
> + using B4::B4;
> template<typename U> T4(U);
> };
> +template<typename T> struct U4 : T4<T> {
> + using T4<T>::T4;
> +};
> T4<void> t4a = {0};
> T4<void> t4b = {0, 0}; // expected-error {{chosen constructor is
> explicit}}
> +U4<void> u4a = {0};
> +U4<void> u4b = {0, 0}; // expected-error {{chosen constructor is
> explicit}}
>
> Modified: cfe/trunk/test/CXX/special/class.inhctor/p4.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> special/class.inhctor/p4.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/special/class.inhctor/p4.cpp (original)
> +++ cfe/trunk/test/CXX/special/class.inhctor/p4.cpp Tue Jun 28 14:03:57
> 2016
> @@ -1,4 +1,7 @@
> // RUN: %clang_cc1 -std=c++11 -verify %s
> +//
> +// Note: [class.inhctor] was removed by P0136R1. This tests the new
> behavior
> +// for the wording that used to be there.
>
> template<int> struct X {};
>
> @@ -8,20 +11,20 @@ struct A {
> public:
> A(X<0>) {}
> protected:
> - A(X<1>) {}
> + A(X<1>) {} // expected-note 2{{declared protected here}}
> private:
> - A(X<2>) {} // expected-note {{declared private here}}
> + A(X<2>) {} // expected-note 2{{declared private here}}
> friend class FA;
> };
>
> struct B : A {
> - using A::A; // expected-error {{private constructor}} expected-note
> {{implicitly declared protected here}}
> + using A::A;
> friend class FB;
> };
>
> B b0{X<0>{}};
> B b1{X<1>{}}; // expected-error {{calling a protected constructor}}
> -B b2{X<2>{}}; // expected-note {{first required here}}
> +B b2{X<2>{}}; // expected-error {{calling a private constructor}}
>
> struct C : B {
> C(X<0> x) : B(x) {}
> @@ -34,7 +37,7 @@ struct FB {
> };
>
> struct FA : A {
> - using A::A; // expected-note 2{{here}}
> + using A::A;
> };
> FA fa0{X<0>{}};
> FA fa1{X<1>{}}; // expected-error {{calling a protected constructor}}
> @@ -47,7 +50,7 @@ struct G {
> template<typename T> G(T*) = delete; // expected-note {{'G<const char>'
> has been explicitly marked deleted here}}
> };
> struct H : G {
> - using G::G; // expected-note 2{{deleted constructor was inherited here}}
> + using G::G;
> };
> H h1(5); // expected-error {{call to deleted constructor of 'H'}}
> H h2("foo"); // expected-error {{call to deleted constructor of 'H'}}
> @@ -57,15 +60,15 @@ H h2("foo"); // expected-error {{call to
> // same signature.
> namespace DRnnnn {
> struct A {
> - constexpr A(int, float = 0) {}
> - explicit A(int, int = 0) {} // expected-note {{constructor cannot be
> inherited}}
> + constexpr A(int, float = 0) {} // expected-note {{candidate}}
> + explicit A(int, int = 0) {} // expected-note {{candidate}}
>
> - A(int, int, int = 0) = delete;
> + A(int, int, int = 0) = delete; // expected-note {{deleted}}
> };
> struct B : A {
> - using A::A; // expected-note {{here}}
> + using A::A; // expected-note 3{{inherited here}}
> };
>
> constexpr B b0(0, 0.0f); // ok, constexpr
> - B b1(0, 1); // expected-error {{call to deleted constructor of
> 'DRnnnn::B'}}
> + B b1(0, 1); // expected-error {{call to constructor of 'DRnnnn::B' is
> ambiguous}}
> }
>
> Modified: cfe/trunk/test/CXX/special/class.inhctor/p7.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> special/class.inhctor/p7.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/special/class.inhctor/p7.cpp (original)
> +++ cfe/trunk/test/CXX/special/class.inhctor/p7.cpp Tue Jun 28 14:03:57
> 2016
> @@ -1,47 +1,48 @@
> // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
> +//
> +// Note: [class.inhctor] was removed by P0136R1. This tests the new
> behavior
> +// for the wording that used to be there.
>
> -// Straight from the standard
> -struct B1 {
> - B1(int); // expected-note {{previous constructor}} expected-note
> {{conflicting constructor}}
> -};
> -struct B2 {
> - B2(int); // expected-note {{conflicting constructor}}
> -};
> -struct D1 : B1, B2 {
> - using B1::B1; // expected-note {{inherited here}}
> - using B2::B2; // expected-error {{already inherited constructor with
> the same signature}}
> +struct B1 { // expected-note 2{{candidate}}
> + B1(int); // expected-note {{candidate}}
> +};
> +struct B2 { // expected-note 2{{candidate}}
> + B2(int); // expected-note {{candidate}}
> +};
> +struct D1 : B1, B2 { // expected-note 2{{candidate}}
> + using B1::B1; // expected-note 3{{inherited here}}
> + using B2::B2; // expected-note 3{{inherited here}}
> };
> struct D2 : B1, B2 {
> using B1::B1;
> using B2::B2;
> D2(int);
> };
> +D1 d1(0); // expected-error {{ambiguous}}
> +D2 d2(0);
>
> template<typename T> struct B3 {
> - B3(T); // expected-note {{previous constructor}}
> + B3(T);
> };
> template<typename T> struct B4 : B3<T>, B1 {
> B4();
> - using B3<T>::B3; // expected-note {{inherited here}}
> - using B1::B1; // expected-error {{already inherited}}
> + using B3<T>::B3;
> + using B1::B1;
> };
> B4<char> b4c;
> -B4<int> b4i; // expected-note {{here}}
> +B4<int> b4i;
>
> struct B5 {
> - template<typename T> B5(T); // expected-note {{previous constructor}}
> + template<typename T> B5(T);
> };
> -struct B6 {
> - template<typename T> B6(T); // expected-note {{conflicting constructor}}
> -};
> -struct B7 {
> - template<typename T, int> B7(T);
> -};
> -struct D56 : B5, B6, B7 {
> - using B5::B5; // expected-note {{inherited here}}
> - using B6::B6; // expected-error {{already inherited}}
> +struct D6 : B5 {
> + using B5::B5;
> + template<typename T> D6(T);
> };
> -struct D57 : B5, B6, B7 {
> +D6 d6(0);
> +struct D7 : B5 {
> using B5::B5;
> - using B7::B7; // ok, not the same signature
> + template<typename T> D7(T, ...);
> };
> +// DRxxx (no number yet): derived class ctor beats base class ctor.
> +D7 d7(0);
>
> Modified: cfe/trunk/test/CXX/special/class.inhctor/p8.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> special/class.inhctor/p8.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/special/class.inhctor/p8.cpp (original)
> +++ cfe/trunk/test/CXX/special/class.inhctor/p8.cpp Tue Jun 28 14:03:57
> 2016
> @@ -1,4 +1,7 @@
> // RUN: %clang_cc1 -std=c++11 -verify %s
> +//
> +// Note: [class.inhctor] was removed by P0136R1. This tests the new
> behavior
> +// for the wording that used to be there.
>
> struct A {
> constexpr A(const int&) : rval(false) {}
> @@ -13,8 +16,6 @@ constexpr int k = 0;
> constexpr A a0{0};
> constexpr A a1{k};
> constexpr B b0{0};
> -// This performs static_cast<(const int&)&&>(k), so calls the A(const
> int&)
> -// constructor.
> constexpr B b1{k};
>
> static_assert(a0.rval && !a1.rval && b0.rval && !b1.rval, "");
> @@ -28,5 +29,4 @@ struct D : C {
> };
> static_assert(D(123).v == 123, "");
>
> -// FIXME: This diagnostic sucks.
> -template<typename T> constexpr D::D(T t) : C(t) {} // expected-error
> {{definition of implicitly declared function}}
> +template<typename T> constexpr D::D(T t) : C(t) {} // expected-error
> {{does not match any declaration in 'D'}}
>
> Added: cfe/trunk/test/CXX/special/class.init/class.inhctor.init/p1.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> special/class.init/class.inhctor.init/p1.cpp?rev=274049&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/special/class.init/class.inhctor.init/p1.cpp
> (added)
> +++ cfe/trunk/test/CXX/special/class.init/class.inhctor.init/p1.cpp Tue
> Jun 28 14:03:57 2016
> @@ -0,0 +1,124 @@
> +// RUN: %clang_cc1 -std=c++11 -verify %s
> +
> +namespace std_example {
> + struct B1 { // expected-note {{declared here}}
> + B1(int, ...) {}
> + };
> +
> + struct B2 {
> + B2(double) {}
> + };
> +
> + int get();
> +
> + struct D1 : B1 { // expected-note {{no default constructor}}
> + using B1::B1; // inherits B1(int, ...)
> + int x;
> + int y = get();
> + };
> +
> + void test() {
> + D1 d(2, 3, 4); // OK: B1 is initialized by calling B1(2, 3, 4),
> + // then d.x is default-initialized (no initialization is performed),
> + // then d.y is initialized by calling get()
> + D1 e; // expected-error {{implicitly-deleted}}
> + }
> +
> + struct D2 : B2 {
> + using B2::B2; // expected-error {{cannot use constructor inherited
> from base class 'B2'; member 'b' of 'std_example::D2' does not have a
> default constructor}}
> + B1 b; // expected-note {{member}}
> + };
> +
> + D2 f(1.0); // expected-note {{inherited constructor for 'D2' first
> required here}}
> +
> + struct W {
> + W(int);
> + };
> + struct X : virtual W {
> + using W::W;
> + X() = delete;
> + };
> + struct Y : X {
> + using X::X;
> + };
> + struct Z : Y, virtual W {
> + using Y::Y;
> + };
> + Z z(0); // OK: initialization of Y does not invoke default constructor
> of X
> +
> + template <class T> struct Log : T {
> + using T::T; // inherits all constructors from class T
> + ~Log() { /* ... */ }
> + };
> +}
> +
> +namespace vbase {
> + struct V { // expected-note 2{{declared here}}
> + V(int);
> + };
> +
> + struct A : virtual V {
> + A() = delete; // expected-note 2{{deleted here}} expected-note
> {{deleted}}
> + using V::V;
> + };
> + struct B : virtual V {
> + B() = delete; // expected-note 2{{deleted here}}
> + B(int, int);
> + using V::V;
> + };
> + struct C : B { // expected-note {{deleted default constructor}}
> + using B::B; // expected-error {{cannot use constructor inherited from
> base class 'B'; base class 'vbase::V' of 'vbase::C' does not have a default
> constructor}}
> + };
> + struct D : A, C { // expected-note {{deleted default constructor}}
> + using A::A;
> + using C::C; // expected-error {{cannot use constructor inherited from
> base class 'C'; base class 'vbase::V' of 'vbase::D' does not have a default
> constructor}} expected-error {{call to deleted constructor of 'vbase::A'}}
> + };
> +
> + A a0; // expected-error {{deleted}}
> + A a1(0);
> + B b0; // expected-error {{deleted}}
> + B b1(0);
> + B b2(0, 0);
> + C c0; // expected-error {{deleted}}
> + C c1(0);
> + C c2(0, 0); // expected-note {{first required here}}
> + D d0; // expected-error {{implicitly-deleted}}
> + D d1(0);
> + D d2(0, 0); // expected-note {{first required here}}
> +}
> +
> +namespace constexpr_init_order {
> + struct Param;
> + struct A {
> + constexpr A(Param);
> + int a;
> + };
> +
> + struct B : A { B(); using A::A; int b = 2; };
> + extern const B b;
> +
> + struct Param {
> + constexpr Param(int c) : n(4 * b.a + b.b + c) {}
> + int n;
> + };
> +
> + constexpr A::A(Param p) : a(p.n) {}
> +
> + constexpr B b(1);
> + constexpr B c(1);
> + static_assert(b.a == 1, "p should be initialized before B() is
> executed");
> + static_assert(c.a == 7, "b not initialzed properly");
> +}
> +
> +namespace default_args {
> + // We work around a defect in P0136R1 where it would reject reasonable
> + // code like the following:
> + struct Base {
> + Base(int = 0);
> + };
> + struct Derived : Base {
> + using Base::Base;
> + };
> + Derived d;
> + // FIXME: Once a fix is standardized, implement it.
> +}
>
> Added: cfe/trunk/test/CXX/special/class.init/class.inhctor.init/p2.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> special/class.init/class.inhctor.init/p2.cpp?rev=274049&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/special/class.init/class.inhctor.init/p2.cpp
> (added)
> +++ cfe/trunk/test/CXX/special/class.init/class.inhctor.init/p2.cpp Tue
> Jun 28 14:03:57 2016
> @@ -0,0 +1,33 @@
> +// RUN: %clang_cc1 -std=c++11 -verify %s
> +
> +namespace std_example {
> + struct A { A(int); };
> + struct B : A { using A::A; };
> +
> + struct C1 : B { using B::B; };
> + struct C2 : B { using B::B; };
> +
> + struct D1 : C1, C2 {
> + using C1::C1; // expected-note {{inherited from base class 'C1' here}}
> + using C2::C2; // expected-note {{inherited from base class 'C2' here}}
> + };
> +
> + struct V1 : virtual B { using B::B; };
> + struct V2 : virtual B { using B::B; };
> +
> + struct D2 : V1, V2 {
> + using V1::V1;
> + using V2::V2;
> + };
> +
> + D1 d1(0); // expected-error {{constructor of 'A' inherited from
> multiple base class subobjects}}
> + D2 d2(0); // OK: initializes virtual B base class, which initializes
> the A base class
> + // then initializes the V1 and V2 base classes as if by a
> defaulted default constructor
> +
> + struct M { M(); M(int); };
> + struct N : M { using M::M; };
> + struct O : M {};
> + struct P : N, O { using N::N; using O::O; };
> + P p(0); // OK: use M(0) to initialize N's base class,
> + // use M() to initialize O's base class
> +}
>
> Modified: cfe/trunk/test/CodeGenCXX/inheriting-constructor.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> CodeGenCXX/inheriting-constructor.cpp?rev=274049&r1=
> 274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CodeGenCXX/inheriting-constructor.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/inheriting-constructor.cpp Tue Jun 28
> 14:03:57 2016
> @@ -1,4 +1,8 @@
> -// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o
> - %s | FileCheck %s
> +// RUN: %clang_cc1 -std=c++11 -triple i386-linux -emit-llvm -o - %s |
> FileCheck %s --check-prefix=CHECK --check-prefix=ITANIUM
> +// RUN: %clang_cc1 -std=c++11 -triple x86_64-darwin -emit-llvm -o - %s |
> FileCheck %s --check-prefix=CHECK --check-prefix=ITANIUM
> +// RUN: %clang_cc1 -std=c++11 -triple arm64-ehabi -emit-llvm -o - %s |
> FileCheck %s --check-prefix=CHECK --check-prefix=ITANIUM
> +// RUN: %clang_cc1 -std=c++11 -triple i386-windows -emit-llvm -o - %s |
> FileCheck %s --check-prefix=CHECK --check-prefix=MSABI --check-prefix=WIN32
> +// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -o - %s |
> FileCheck %s --check-prefix=CHECK --check-prefix=MSABI --check-prefix=WIN64
>
> // PR12219
> struct A { A(int); virtual ~A(); };
> @@ -11,18 +15,396 @@ struct C { template<typename T> C(T); };
> struct D : C { using C::C; };
> D d(123);
>
> -// CHECK-LABEL: define void @_ZN1BD2Ev
> -// CHECK-LABEL: define void @_ZN1BD1Ev
> -// CHECK-LABEL: define void @_ZN1BD0Ev
> +// ITANIUM-LABEL: define void @_ZN1BD2Ev
> +// ITANIUM-LABEL: define void @_ZN1BD1Ev
> +// ITANIUM-LABEL: define void @_ZN1BD0Ev
> +// WIN32-LABEL: define {{.*}}void @"\01??1B@@UAE at XZ"
> +// WIN64-LABEL: define {{.*}}void @"\01??1B@@UEAA at XZ"
>
> -// CHECK-LABEL: define linkonce_odr void @_ZN1BC1Ei(
> -// CHECK: call void @_ZN1BC2Ei(
> +// ITANIUM-LABEL: define linkonce_odr void @_ZN1BCI11AEi(
> +// ITANIUM: call void @_ZN1BCI21AEi(
>
> -// CHECK-LABEL: define linkonce_odr void @_ZN1DC1IiEET_(
> -// CHECK: call void @_ZN1DC2IiEET_(
> +// ITANIUM-LABEL: define linkonce_odr void @_ZN1DCI11CIiEET_(
> +// ITANIUM: call void @_ZN1DCI21CIiEET_(
>
> -// CHECK-LABEL: define linkonce_odr void @_ZN1BC2Ei(
> -// CHECK: call void @_ZN1AC2Ei(
> +// WIN32-LABEL: define internal {{.*}} @"\01??0B@@QAE at H@Z"(
> +// WIN32: call {{.*}} @"\01??0A@@QAE at H@Z"(
> +// WIN64-LABEL: define internal {{.*}} @"\01??0B@@QEAA at H@Z"(
> +// WIN64: call {{.*}} @"\01??0A@@QEAA at H@Z"(
>
> -// CHECK-LABEL: define linkonce_odr void @_ZN1DC2IiEET_(
> -// CHECK: call void @_ZN1CC2IiEET_(
> +// WIN32-LABEL: define internal {{.*}} @"\01??0D@@QAE at H@Z"(
> +// WIN32: call {{.*}} @"\01??$?0H at C@@QAE at H@Z"
> +// WIN64-LABEL: define internal {{.*}} @"\01??0D@@QEAA at H@Z"(
> +// WIN64: call {{.*}} @"\01??$?0H at C@@QEAA at H@Z"
> +
> +struct Q { Q(int); Q(const Q&); ~Q(); };
> +struct Z { Z(); Z(int); ~Z(); int n; };
> +
> +namespace noninline_nonvirt {
> + struct A { A(int, Q&&, void *__attribute__((pass_object_size(0))));
> int n; };
> + struct B : Z, A { Z z; using A::A; };
> + B b(1, 2, &b);
> + // ITANIUM-LABEL: define {{.*}} @__cxx_global_var_init
> + // ITANIUM: call void @_ZN1QC1Ei({{.*}} %[[TMP:.*]], i32 2)
> + // ITANIUM: call void @_ZN17noninline_nonvirt1BCI1NS_
> 1AEEiO1QPvU17pass_object_size0({{.*}} @_ZN17noninline_nonvirt1bE, i32 1,
> {{.*}} %[[TMP]], i8* {{.*}} @_ZN17noninline_nonvirt1bE{{.*}}, i{{32|64}}
> 12)
> + // ITANIUM: call void @_ZN1QD1Ev({{.*}} %[[TMP]])
> + // ITANIUM: call i32 @__cxa_atexit(
> +
> + // Complete object ctor for B delegates to base object ctor.
> + // ITANIUM-LABEL: define linkonce_odr void @_ZN17noninline_
> nonvirt1BCI1NS_1AEEiO1QPvU17pass_object_size0(
> + // ITANIUM: call void @_ZN17noninline_nonvirt1BCI2NS_
> 1AEEiO1QPvU17pass_object_size0({{.*}}, i32 {{.*}}, %{{.*}}* {{.*}}, i8*
> {{.*}}, i{{32|64}} {{.*}})
> +
> + // In MSABI, we don't have ctor variants. B ctor forwards to A ctor.
> + // MSABI-LABEL: define internal {{.*}} @"\01??0B at noninline_nonvirt@@
> Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0 at __clang@@@Z"(%{{.*}},
> i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
> + // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"(
> + // MSABI: call {{.*}} @"\01??0A at noninline_nonvirt@@Q{{AE|EAA}}@H
> $$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0 at __clang@@@Z"(%{{.*}},
> i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
> + // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"(
> +
> + struct C : B { using B::B; };
> + C c(1, 2, &c);
> + // Complete object ctor for C delegates.
> + // ITANIUM-LABEL: define linkonce_odr void @_ZN17noninline_
> nonvirt1CCI1NS_1AEEiO1QPvU17pass_object_size0(
> + // ITANIUM: call void @_ZN17noninline_nonvirt1CCI2NS_
> 1AEEiO1QPvU17pass_object_size0({{.*}}, i32 {{.*}}, %{{.*}}* {{.*}}, i8*
> {{.*}}, i{{32|64}} {{.*}})
> +
> + // MSABI-LABEL: define internal {{.*}} @"\01??0C at noninline_nonvirt@@
> Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0 at __clang@@@Z"(%{{.*}},
> i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
> + // MSABI: call {{.*}} @"\01??0B at noninline_nonvirt@@Q{{AE|EAA}}@H
> $$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0 at __clang@@@Z"(%{{.*}},
> i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
> +}
> +
> +namespace noninline_virt {
> + struct A { A(int, Q&&, void *__attribute__((pass_object_size(0))));
> int n; };
> + struct B : Z, virtual A { Z z; using A::A; };
> + B b(1, 2, &b);
> + // Complete object ctor forwards to A ctor then constructs Zs.
> + // ITANIUM-LABEL: define linkonce_odr void @_ZN14noninline_virt1BCI1NS_
> 1AEEiO1QPvU17pass_object_size0(
> + // ITANIUM: call void @_ZN14noninline_virt1AC2EiO1QPvU17pass_object_size0({{.*}}
> %{{.*}}, i32 %{{.*}}, %{{.*}}* {{.*}}, i8* {{.*}}, i{{32|64}} %{{.*}}
> + // ITANIUM: call void @_ZN1ZC2Ev(
> + // ITANIUM: store {{.*}} @_ZTVN14noninline_virt1BE
> + // ITANIUM: call void @_ZN1ZC1Ev(
> +
> + // MSABI-LABEL: define internal {{.*}} @"\01??0B at noninline_virt@@Q{{
> AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0 at __clang@@@Z"(%{{.*}},
> i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 %{{.*}})
> + // MSABI: %[[COMPLETE:.*]] = icmp ne
> + // MSABI: br i1 %[[COMPLETE]],
> + // MSABI: call {{.*}} @"\01??0A at noninline_virt@@Q{{AE|EAA}}@H
> $$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0 at __clang@@@Z"(%{{.*}},
> i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
> + // MSABI: br
> + // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"(
> + // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"(
> +
> + struct C : B { using B::B; };
> + C c(1, 2, &c);
> + // Complete object ctor forwards to A ctor, then calls B's base
> inheriting
> + // constructor, which takes no arguments other than the this pointer
> and VTT.
> + // ITANIUM_LABEL: define linkonce_odr void @_ZN14noninline_virt1CCI1NS_
> 1AEEiO1QPvU17pass_object_size0(
> + // ITANIUM: call void @_ZN14noninline_virt1AC2EiO1QPvU17pass_object_size0({{.*}}
> %{{.*}}, i32 %{{.*}}, %{{.*}}* {{.*}}, i8* %{{.*}}, i{{32|64}} %{{.*}})
> + // ITANIUM: call void @_ZN14noninline_virt1BCI2NS_
> 1AEEiO1QPvU17pass_object_size0(%{{.*}}* %{{.*}}, i8** getelementptr
> inbounds ([2 x i8*], [2 x i8*]* @_ZTTN14noninline_virt1CE, i64 0, i64 1))
> + // ITANIUM: store {{.*}} @_ZTVN14noninline_virt1CE
> +
> + // C constructor forwards to B constructor and A constructor. We pass
> the args
> + // to both. FIXME: Can we pass undef here instead, for the base object
> + // constructor call?
> + // MSABI-LABEL: define internal {{.*}} @"\01??0C at noninline_virt@@Q{{
> AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0 at __clang@@@Z"(%{{.*}},
> i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 %{{.*}})
> + // MSABI: %[[COMPLETE:.*]] = icmp ne
> + // MSABI: br i1 %[[COMPLETE]],
> + // MSABI: call {{.*}} @"\01??0A at noninline_virt@@Q{{AE|EAA}}@H
> $$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0 at __clang@@@Z"(%{{.*}},
> i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
> + // MSABI: br
> + // MSABI: call {{.*}} @"\01??0B at noninline_virt@@Q{{AE|EAA}}@H
> $$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0 at __clang@@@Z"(%{{.*}},
> i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 0)
> +}
> +
> +// For MSABI only, check that inalloca arguments result in inlining.
> +namespace inalloca_nonvirt {
> + struct A { A(Q, int, Q, Q&&); int n; };
> + struct B : Z, A { Z z; using A::A; };
> + B b(1, 2, 3, 4);
> + // No inlining implied for Itanium.
> + // ITANIUM-LABEL: define linkonce_odr void
> @_ZN16inalloca_nonvirt1BCI1NS_1AEE1QiS1_OS1_(
> + // ITANIUM: call void @_ZN16inalloca_nonvirt1BCI2NS_1AEE1QiS1_OS1_(
> +
> + // MSABI-LABEL: define internal void @"\01??__Eb at inalloca_nonvirt@@
> YAXXZ"(
> +
> + // On Win32, the inalloca call can't be forwarded so we force inlining.
> + // WIN32: %[[TMP:.*]] = alloca
> + // WIN32: call i8* @llvm.stacksave()
> + // WIN32: %[[ARGMEM:.*]] = alloca inalloca
> + // WIN32: call {{.*}} @"\01??0Q@@QAE at H@Z"(%{{.*}}* %[[TMP]], i32 4)
> + // WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: call {{.*}} @"\01??0Q@@QAE at H@Z"({{.*}}* %[[ARG3]], i32 3)
> + // WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: call {{.*}} @"\01??0Q@@QAE at H@Z"({{.*}}* %[[ARG1]], i32 1)
> + // WIN32: call {{.*}} @"\01??0Z@@QAE at XZ"(
> + // WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: store i32 2, i32* %[[ARG2]]
> + // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
> + // WIN32: call {{.*}} @"\01??0A at inalloca_nonvirt@@QAE at UQ@@H0$$QAU2@
> @Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
> + // WIN32: call void @llvm.stackrestore(
> + // WIN32: call {{.*}} @"\01??0Z@@QAE at XZ"(
> + // WIN32: call {{.*}} @"\01??_DQ@@QAE at XZ"(
> +
> + // On Win64, the Q arguments would be destroyed in the callee. We don't
> yet
> + // support that in the non-inlined case, so we force inlining.
> + // WIN64: %[[TMP:.*]] = alloca
> + // WIN64: %[[ARG3:.*]] = alloca
> + // WIN64: %[[ARG1:.*]] = alloca
> + // WIN64: call {{.*}} @"\01??0Q@@QEAA at H@Z"({{.*}}* %[[TMP]], i32 4)
> + // WIN64: call {{.*}} @"\01??0Q@@QEAA at H@Z"({{.*}}* %[[ARG3]], i32 3)
> + // WIN64: call {{.*}} @"\01??0Q@@QEAA at H@Z"({{.*}}* %[[ARG1]], i32 1)
> + // WIN64: call {{.*}} @"\01??0Z@@QEAA at XZ"(
> + // WIN64: call {{.*}} @"\01??0A at inalloca_nonvirt@@QEAA at UQ@@H0$$QEAU2@
> @Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}}
> %[[TMP]])
> + // WIN64: call {{.*}} @"\01??0Z@@QEAA at XZ"(
> + // WIN64: call void @"\01??_DQ@@QEAA at XZ"({{.*}}* %[[TMP]])
> +
> + struct C : B { using B::B; };
> + C c(1, 2, 3, 4);
> + // MSABI-LABEL: define internal void @"\01??__Ec at inalloca_nonvirt@@
> YAXXZ"(
> +
> + // On Win32, the inalloca call can't be forwarded so we force inlining.
> + // WIN32: %[[TMP:.*]] = alloca
> + // WIN32: call i8* @llvm.stacksave()
> + // WIN32: %[[ARGMEM:.*]] = alloca inalloca
> + // WIN32: call {{.*}} @"\01??0Q@@QAE at H@Z"(%{{.*}}* %[[TMP]], i32 4)
> + // WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: call {{.*}} @"\01??0Q@@QAE at H@Z"({{.*}}* %[[ARG3]], i32 3)
> + // WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: call {{.*}} @"\01??0Q@@QAE at H@Z"({{.*}}* %[[ARG1]], i32 1)
> + // WIN32: call {{.*}} @"\01??0Z@@QAE at XZ"(
> + // WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: store i32 2, i32* %[[ARG2]]
> + // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
> + // WIN32: call {{.*}} @"\01??0A at inalloca_nonvirt@@QAE at UQ@@H0$$QAU2@
> @Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
> + // WIN32: call void @llvm.stackrestore(
> + // WIN32: call {{.*}} @"\01??0Z@@QAE at XZ"(
> + // WIN32: call {{.*}} @"\01??_DQ@@QAE at XZ"(
> +
> + // On Win64, the Q arguments would be destroyed in the callee. We don't
> yet
> + // support that in the non-inlined case, so we force inlining.
> + // WIN64: %[[TMP:.*]] = alloca
> + // WIN64: %[[ARG3:.*]] = alloca
> + // WIN64: %[[ARG1:.*]] = alloca
> + // WIN64: call {{.*}} @"\01??0Q@@QEAA at H@Z"({{.*}}* %[[TMP]], i32 4)
> + // WIN64: call {{.*}} @"\01??0Q@@QEAA at H@Z"({{.*}}* %[[ARG3]], i32 3)
> + // WIN64: call {{.*}} @"\01??0Q@@QEAA at H@Z"({{.*}}* %[[ARG1]], i32 1)
> + // WIN64: call {{.*}} @"\01??0Z@@QEAA at XZ"(
> + // WIN64: call {{.*}} @"\01??0A at inalloca_nonvirt@@QEAA at UQ@@H0$$QEAU2@
> @Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}}
> %[[TMP]])
> + // WIN64: call {{.*}} @"\01??0Z@@QEAA at XZ"(
> + // WIN64: call void @"\01??_DQ@@QEAA at XZ"({{.*}}* %[[TMP]])
> +}
> +
> +namespace inalloca_virt {
> + struct A { A(Q, int, Q, Q&&); int n; };
> + struct B : Z, virtual A { Z z; using A::A; };
> + B b(1, 2, 3, 4);
> +
> + // MSABI-LABEL: define internal void @"\01??__Eb at inalloca_virt@@YAXXZ"(
> +
> + // On Win32, the inalloca call can't be forwarded so we force inlining.
> + // WIN32: %[[TMP:.*]] = alloca
> + // WIN32: call i8* @llvm.stacksave()
> + // WIN32: %[[ARGMEM:.*]] = alloca inalloca
> + // WIN32: call {{.*}} @"\01??0Q@@QAE at H@Z"(%{{.*}}* %[[TMP]], i32 4)
> + // WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: call {{.*}} @"\01??0Q@@QAE at H@Z"({{.*}}* %[[ARG3]], i32 3)
> + // WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: call {{.*}} @"\01??0Q@@QAE at H@Z"({{.*}}* %[[ARG1]], i32 1)
> + // FIXME: It's dumb to round-trip this though memory and generate a
> branch.
> + // WIN32: store i32 1, i32* %[[IS_MOST_DERIVED_ADDR:.*]]
> + // WIN32: %[[IS_MOST_DERIVED:.*]] = load i32, i32*
> %[[IS_MOST_DERIVED_ADDR]]
> + // WIN32: %[[IS_MOST_DERIVED_i1:.*]] = icmp ne i32
> %[[IS_MOST_DERIVED]], 0
> + // WIN32: br i1 %[[IS_MOST_DERIVED_i1]]
> + //
> + // WIN32: store {{.*}} @"\01??_8B at inalloca_virt@@7B@"
> + // WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: store i32 2, i32* %[[ARG2]]
> + // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
> + // WIN32: call {{.*}} @"\01??0A at inalloca_virt@@QAE at UQ@@H0$$QAU2@@Z"(%{{[^,]*}},
> <{{.*}}>* inalloca %[[ARGMEM]])
> + // WIN32: call void @llvm.stackrestore(
> + // WIN32: br
> + //
> + // Note that if we jumped directly to here we would fail to
> stackrestore and
> + // destroy the parameters, but that's not actually possible.
> + // WIN32: call {{.*}} @"\01??0Z@@QAE at XZ"(
> + // WIN32: call {{.*}} @"\01??0Z@@QAE at XZ"(
> + // WIN32: call {{.*}} @"\01??_DQ@@QAE at XZ"(
> +
> + // On Win64, the Q arguments would be destroyed in the callee. We don't
> yet
> + // support that in the non-inlined case, so we force inlining.
> + // WIN64: %[[TMP:.*]] = alloca
> + // WIN64: %[[ARG3:.*]] = alloca
> + // WIN64: %[[ARG1:.*]] = alloca
> + // WIN64: call {{.*}} @"\01??0Q@@QEAA at H@Z"({{.*}}* %[[TMP]], i32 4)
> + // WIN64: call {{.*}} @"\01??0Q@@QEAA at H@Z"({{.*}}* %[[ARG3]], i32 3)
> + // WIN64: call {{.*}} @"\01??0Q@@QEAA at H@Z"({{.*}}* %[[ARG1]], i32 1)
> + // WIN64: br i1
> + // WIN64: call {{.*}} @"\01??0A at inalloca_virt@@QEAA at UQ@@H0$$QEAU2@@Z"(%{{.*}},
> %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
> + // WIN64: br
> + // WIN64: call {{.*}} @"\01??0Z@@QEAA at XZ"(
> + // WIN64: call {{.*}} @"\01??0Z@@QEAA at XZ"(
> + // WIN64: call void @"\01??_DQ@@QEAA at XZ"({{.*}}* %[[TMP]])
> +
> + struct C : B { using B::B; };
> + C c(1, 2, 3, 4);
> + // ITANIUM-LABEL: define linkonce_odr void @_ZN13inalloca_virt1CD1Ev(
> +
> + // MSABI-LABEL: define internal void @"\01??__Ec at inalloca_virt@@YAXXZ"(
> +
> + // On Win32, the inalloca call can't be forwarded so we force inlining.
> + // WIN32: %[[TMP:.*]] = alloca
> + // WIN32: call i8* @llvm.stacksave()
> + // WIN32: %[[ARGMEM:.*]] = alloca inalloca
> + // WIN32: call {{.*}} @"\01??0Q@@QAE at H@Z"(%{{.*}}* %[[TMP]], i32 4)
> + // WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: call {{.*}} @"\01??0Q@@QAE at H@Z"({{.*}}* %[[ARG3]], i32 3)
> + // WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: call {{.*}} @"\01??0Q@@QAE at H@Z"({{.*}}* %[[ARG1]], i32 1)
> + // WIN32: store i32 1, i32* %[[IS_MOST_DERIVED_ADDR:.*]]
> + // WIN32: %[[IS_MOST_DERIVED:.*]] = load i32, i32*
> %[[IS_MOST_DERIVED_ADDR]]
> + // WIN32: %[[IS_MOST_DERIVED_i1:.*]] = icmp ne i32
> %[[IS_MOST_DERIVED]], 0
> + // WIN32: br i1 %[[IS_MOST_DERIVED_i1]]
> + //
> + // WIN32: store {{.*}} @"\01??_8C at inalloca_virt@@7B@"
> + // WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: store i32 2, i32* %[[ARG2]]
> + // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
> + // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
> + // WIN32: call {{.*}} @"\01??0A at inalloca_virt@@QAE at UQ@@H0$$QAU2@@Z"(%{{[^,]*}},
> <{{.*}}>* inalloca %[[ARGMEM]])
> + // WIN32: call void @llvm.stackrestore(
> + // WIN32: br
> + //
> + // WIN32: store i32 0, i32* %[[IS_MOST_DERIVED_ADDR:.*]]
> + // WIN32: %[[IS_MOST_DERIVED:.*]] = load i32, i32*
> %[[IS_MOST_DERIVED_ADDR]]
> + // WIN32: %[[IS_MOST_DERIVED_i1:.*]] = icmp ne i32
> %[[IS_MOST_DERIVED]], 0
> + // WIN32: br i1 %[[IS_MOST_DERIVED_i1]]
> + //
> + // Note: this block is unreachable.
> + // WIN32: store {{.*}} @"\01??_8B at inalloca_virt@@7B@"
> + // WIN32: br
> + //
> + // WIN32: call {{.*}} @"\01??0Z@@QAE at XZ"(
> + // WIN32: call {{.*}} @"\01??0Z@@QAE at XZ"(
> + // WIN32: call {{.*}} @"\01??_DQ@@QAE at XZ"(
> +
> + // On Win64, the Q arguments would be destroyed in the callee. We don't
> yet
> + // support that in the non-inlined case, so we force inlining.
> + // WIN64: %[[TMP:.*]] = alloca
> + // WIN64: %[[ARG3:.*]] = alloca
> + // WIN64: %[[ARG1:.*]] = alloca
> + // WIN64: call {{.*}} @"\01??0Q@@QEAA at H@Z"({{.*}}* %[[TMP]], i32 4)
> + // WIN64: call {{.*}} @"\01??0Q@@QEAA at H@Z"({{.*}}* %[[ARG3]], i32 3)
> + // WIN64: call {{.*}} @"\01??0Q@@QEAA at H@Z"({{.*}}* %[[ARG1]], i32 1)
> + // WIN64: br i1
> + // WIN64: store {{.*}} @"\01??_8C at inalloca_virt@@7B@"
> + // WIN64: call {{.*}} @"\01??0A at inalloca_virt@@QEAA at UQ@@H0$$QEAU2@@Z"(%{{.*}},
> %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
> + // WIN64: br
> + // WIN64: br i1
> + // (Unreachable block)
> + // WIN64: store {{.*}} @"\01??_8B at inalloca_virt@@7B@"
> + // WIN64: br
> + // WIN64: call {{.*}} @"\01??0Z@@QEAA at XZ"(
> + // WIN64: call {{.*}} @"\01??0Z@@QEAA at XZ"(
> + // WIN64: call void @"\01??_DQ@@QEAA at XZ"({{.*}}* %[[TMP]])
> +}
> +
> +namespace inline_nonvirt {
> + struct A { A(Q, int, Q, Q&&, ...); int n; };
> + struct B : Z, A { Z z; using A::A; };
> + B b(1, 2, 3, 4, 5, 6);
> + // Inlined all the way down to the A ctor.
> + // ITANIUM-LABEL: define {{.*}} @__cxx_global_var_init
> + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 1)
> + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 3)
> + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 4)
> + // ITANIUM: %[[Z_BASE:.*]] = bitcast %{{.*}}* %[[THIS:.*]] to
> + // ITANIUM: call void @_ZN1ZC2Ev(
> + // ITANIUM: %[[B_CAST:.*]] = bitcast {{.*}} %[[THIS]]
> + // ITANIUM: %[[A_CAST:.*]] = getelementptr {{.*}} %[[B_CAST]],
> i{{32|64}} 4
> + // ITANIUM: %[[A:.*]] = bitcast {{.*}} %[[A_CAST]]
> + // ITANIUM: call void ({{.*}}, ...) @_ZN14inline_
> nonvirt1AC2E1QiS1_OS1_z(%{{.*}}* %[[A]], {{.*}}, i32 2, {{.*}}, {{.*}},
> i32 5, i32 6)
> + // ITANIUM: %[[Z_MEMBER:.*]] = getelementptr {{.*}} %[[THIS]], i32 0,
> i32 2
> + // ITANIUM: call void @_ZN1ZC1Ev({{.*}} %[[Z_MEMBER]])
> + // ITANIUM: call void @_ZN1QD1Ev(
> + // ITANIUM: call void @_ZN1QD1Ev(
> + // ITANIUM: call void @_ZN1QD1Ev(
> +
> + struct C : B { using B::B; };
> + C c(1, 2, 3, 4, 5, 6);
> + // Inlined all the way down to the A ctor.
> + // ITANIUM-LABEL: define {{.*}} @__cxx_global_var_init
> + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 1)
> + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 3)
> + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 4)
> + // ITANIUM: %[[Z_BASE:.*]] = bitcast %{{.*}}* %[[THIS:.*]] to
> + // ITANIUM: call void @_ZN1ZC2Ev(
> + // ITANIUM: %[[B_CAST:.*]] = bitcast {{.*}} %[[THIS]]
> + // ITANIUM: %[[A_CAST:.*]] = getelementptr {{.*}} %[[B_CAST]],
> i{{32|64}} 4
> + // ITANIUM: %[[A:.*]] = bitcast {{.*}} %[[A_CAST]]
> + // ITANIUM: call void ({{.*}}, ...) @_ZN14inline_
> nonvirt1AC2E1QiS1_OS1_z(%{{.*}}* %[[A]], {{.*}}, i32 2, {{.*}}, {{.*}},
> i32 5, i32 6)
> + // ITANIUM: %[[Z_MEMBER:.*]] = getelementptr {{.*}} %{{.*}}, i32 0, i32
> 2
> + // ITANIUM: call void @_ZN1ZC1Ev({{.*}} %[[Z_MEMBER]])
> + // ITANIUM: call void @_ZN1QD1Ev(
> + // ITANIUM: call void @_ZN1QD1Ev(
> + // ITANIUM: call void @_ZN1QD1Ev(
> +}
> +
> +namespace inline_virt {
> + struct A { A(Q, int, Q, Q&&, ...); int n; };
> + struct B : Z, virtual A { Z z; using A::A; };
> + B b(1, 2, 3, 4, 5, 6);
> + // Inlined all the way down to the A ctor.
> + // ITANIUM-LABEL: define {{.*}} @__cxx_global_var_init
> + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 1)
> + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 3)
> + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 4)
> + // ITANIUM: %[[B_CAST:.*]] = bitcast {{.*}} %[[THIS:.*]]
> + // ITANIUM: %[[A_CAST:.*]] = getelementptr {{.*}} %[[B_CAST]],
> i{{32|64}} {{12|16}}
> + // ITANIUM: %[[A:.*]] = bitcast {{.*}} %[[A_CAST]]
> + // ITANIUM: call void ({{.*}}, ...) @_ZN11inline_virt1AC2E1QiS1_OS1_z(%{{.*}}*
> %[[A]], {{.*}}, i32 2, {{.*}}, {{.*}}, i32 5, i32 6)
> + // ITANIUM: call void @_ZN1ZC2Ev(
> + // ITANIUM: call void @_ZN1ZC1Ev(
> + // ITANIUM: call void @_ZN1QD1Ev(
> + // ITANIUM: call void @_ZN1QD1Ev(
> + // ITANIUM: call void @_ZN1QD1Ev(
> +
> + struct C : B { using B::B; };
> + C c(1, 2, 3, 4, 5, 6);
> + // Inlined all the way down to the A ctor, except that we can just call
> the
> + // B base inheriting constructor to construct that portion (it doesn't
> need
> + // the forwarded arguments).
> + // ITANIUM-LABEL: define {{.*}} @__cxx_global_var_init
> + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 1)
> + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 3)
> + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 4)
> + // ITANIUM: %[[B_CAST:.*]] = bitcast {{.*}} %[[THIS:.*]]
> + // ITANIUM: %[[A_CAST:.*]] = getelementptr {{.*}} %[[B_CAST]],
> i{{32|64}} {{12|16}}
> + // ITANIUM: %[[A:.*]] = bitcast {{.*}} %[[A_CAST]]
> + // ITANIUM: call void ({{.*}}, ...) @_ZN11inline_virt1AC2E1QiS1_OS1_z(%{{.*}}*
> %[[A]], {{.*}}, i32 2, {{.*}}, {{.*}}, i32 5, i32 6)
> + // ITANIUM: call void @_ZN11inline_virt1BCI2NS_1AEE1QiS1_OS1_z({{[^,]*}},
> i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @_ZTTN11inline_virt1CE,
> i64 0, i64 1))
> + // ITANIUM: store {{.*}} @_ZTVN11inline_virt1CE
> + // ITANIUM: call void @_ZN1QD1Ev(
> + // ITANIUM: call void @_ZN1QD1Ev(
> + // ITANIUM: call void @_ZN1QD1Ev(
> +
> + // B base object inheriting constructor does not get passed arguments.
> + // ITANIUM-LABEL: define linkonce_odr void @_ZN11inline_virt1BCI2NS_
> 1AEE1QiS1_OS1_z(
> + // ITANIUM-NOT: call
> + // ITANIUM: call void @_ZN1ZC2Ev(%struct.Z* %2)
> + // ITANIUM-NOT: call
> + // VTT -> vtable
> + // ITANIUM: store
> + // ITANIUM-NOT: call
> + // ITANIUM: call void @_ZN1ZC1Ev(%struct.Z* %z)
> + // ITANIUM-NOT: call
> + // ITANIUM: }
> +}
> +
> +// ITANIUM-LABEL: define linkonce_odr void @_ZN1BCI21AEi(
> +// ITANIUM: call void @_ZN1AC2Ei(
> +
> +// ITANIUM-LABEL: define linkonce_odr void @_ZN1DCI21CIiEET_(
> +// ITANIUM: call void @_ZN1CC2IiEET_(
> +
> +// ITANIUM-LABEL: define linkonce_odr void @_ZN17noninline_
> nonvirt1BCI2NS_1AEEiO1QPvU17pass_object_size0(
> +// ITANIUM: call void @_ZN1ZC2Ev(
> +// ITANIUM: call void @_ZN17noninline_nonvirt1AC2EiO1QPvU17pass_
> object_size0(
> +
> +// ITANIUM-LABEL: define linkonce_odr void @_ZN17noninline_
> nonvirt1CCI2NS_1AEEiO1QPvU17pass_object_size0(
> +// ITANIUM: call void @_ZN17noninline_nonvirt1BCI2NS_
> 1AEEiO1QPvU17pass_object_size0(
>
> Modified: cfe/trunk/test/PCH/cxx11-inheriting-ctors.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/
> cxx11-inheriting-ctors.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/PCH/cxx11-inheriting-ctors.cpp (original)
> +++ cfe/trunk/test/PCH/cxx11-inheriting-ctors.cpp Tue Jun 28 14:03:57 2016
> @@ -1,10 +1,19 @@
> -// RUN: %clang_cc1 -std=c++11 -emit-pch -o %t %s
> -// RUN: %clang_cc1 -std=c++11 -include-pch %t -verify %s
> +// RUN: %clang_cc1 -std=c++11 -include %s -include %s -verify %s
> +//
> +// Emit with definitions in the declaration:
> +// RxN: %clang_cc1 -std=c++11 -emit-pch -o %t.12 -include %s %s
> +// RxN: %clang_cc1 -std=c++11 -include-pch %t.12 -verify %s
> +//
> +// Emit with definitions in update records:
> +// RxN: %clang_cc1 -std=c++11 -emit-pch -o %t.1 %s
> +// RxN: %clang_cc1 -std=c++11 -include-pch %t.1 -emit-pch -o %t.2 -verify
> %s
> +// RxN: %clang_cc1 -std=c++11 -include-pch %t.1 -include-pch %t.2 -verify
> %s
> +
>
> // expected-no-diagnostics
>
> -#ifndef HEADER_INCLUDED
> -#define HEADER_INCLUDED
> +#ifndef HEADER1
> +#define HEADER1
>
> struct Base {
> Base(int) {}
> @@ -27,7 +36,8 @@ struct Test3 : B {
> using B::B;
> };
>
> -#else
> +#elif !defined(HEADER2)
> +#define HEADER2
>
> Test test1a(42);
> Test test1b(nullptr);
> @@ -36,4 +46,16 @@ Test2<int> test2b(nullptr);
> Test3<Base> test3a(42);
> Test3<Base> test3b(nullptr);
>
> -#endif // HEADER_INCLUDED
> +#pragma clang __debug dump Test
> +#pragma clang __debug dump Test2
> +
> +#else
> +
> +Test retest1a(42);
> +Test retest1b(nullptr);
> +Test2<int> retest2a(42);
> +Test2<int> retest2b(nullptr);
> +Test3<Base> retest3a(42);
> +Test3<Base> retest3b(nullptr);
> +
> +#endif
>
> Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> SemaCXX/constant-expression-cxx11.cpp?rev=274049&r1=
> 274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
> +++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Tue Jun 28
> 14:03:57 2016
> @@ -2029,3 +2029,40 @@ namespace IncompleteClass {
> static constexpr int j = g(static_cast<XX*>(nullptr)); //
> expected-error {{constexpr variable 'j' must be initialized by a constant
> expression}} expected-note {{undefined function 'g' cannot be used in a
> constant expression}}
> };
> }
> +
> +namespace InheritedCtor {
> + struct A { constexpr A(int) {} };
> +
> + struct B : A { int n; using A::A; }; // expected-note {{here}}
> + constexpr B b(0); // expected-error {{constant expression}}
> expected-note {{derived class}}
> +
> + struct C : A { using A::A; struct { union { int n, m = 0; }; union {
> int a = 0; }; int k = 0; }; struct {}; union {}; }; // expected-warning
> 4{{extension}}
> + constexpr C c(0);
> +
> + struct D : A {
> + using A::A; // expected-note {{here}}
> + struct { // expected-warning {{extension}}
> + union { // expected-warning {{extension}}
> + int n;
> + };
> + };
> + };
> + constexpr D d(0); // expected-error {{constant expression}}
> expected-note {{derived class}}
> +
> + struct E : virtual A { using A::A; }; // expected-note {{here}}
> + // We wrap a function around this to avoid implicit zero-initialization
> + // happening first; the zero-initialization step would produce the same
> + // error and defeat the point of this test.
> + void f() {
> + constexpr E e(0); // expected-error {{constant expression}}
> expected-note {{derived class}}
> + }
> + // FIXME: This produces a note with no source location.
> + //constexpr E e(0);
> +
> + struct W { constexpr W(int n) : w(n) {} int w; };
> + struct X : W { using W::W; int x = 2; };
> + struct Y : X { using X::X; int y = 3; };
> + struct Z : Y { using Y::Y; int z = 4; };
> + constexpr Z z(1);
> + static_assert(z.w == 1 && z.x == 2 && z.y == 3 && z.z == 4, "");
> +}
>
> Modified: cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> SemaCXX/cxx11-inheriting-ctors.cpp?rev=274049&r1=
> 274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp (original)
> +++ cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp Tue Jun 28 14:03:57
> 2016
> @@ -34,3 +34,13 @@ namespace WrongIdent {
> using B::A;
> };
> }
> +
> +namespace DefaultCtorConflict {
> + struct A { A(int = 0); };
> + struct B : A {
> + using A::A;
> + } b; // ok, not ambiguous, inherited constructor suppresses implicit
> default constructor
> + struct C {
> + B b;
> + } c;
> +}
>
> Modified: cfe/trunk/tools/libclang/CIndex.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/
> libclang/CIndex.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/tools/libclang/CIndex.cpp (original)
> +++ cfe/trunk/tools/libclang/CIndex.cpp Tue Jun 28 14:03:57 2016
> @@ -3955,6 +3955,9 @@ static const Decl *getDeclFromExpr(const
> if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E))
> if (!CE->isElidable())
> return CE->getConstructor();
> + if (const CXXInheritedCtorInitExpr *CE =
> + dyn_cast<CXXInheritedCtorInitExpr>(E))
> + return CE->getConstructor();
> if (const ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(E))
> return OME->getMethodDecl();
>
> @@ -5665,6 +5668,7 @@ CXCursor clang_getCursorDefinition(CXCur
> D->getLocation(), TU);
>
> case Decl::UsingShadow:
> + case Decl::ConstructorUsingShadow:
> return clang_getCursorDefinition(
> MakeCXCursor(cast<UsingShadowDecl>(D)->
> getTargetDecl(),
> TU));
>
> Modified: cfe/trunk/tools/libclang/CXCursor.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/
> libclang/CXCursor.cpp?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/tools/libclang/CXCursor.cpp (original)
> +++ cfe/trunk/tools/libclang/CXCursor.cpp Tue Jun 28 14:03:57 2016
> @@ -504,6 +504,7 @@ CXCursor cxcursor::MakeCXCursor(const St
> case Stmt::CXXMemberCallExprClass:
> case Stmt::CUDAKernelCallExprClass:
> case Stmt::CXXConstructExprClass:
> + case Stmt::CXXInheritedCtorInitExprClass:
> case Stmt::CXXTemporaryObjectExprClass:
> case Stmt::CXXUnresolvedConstructExprClass:
> case Stmt::UserDefinedLiteralClass:
>
> Modified: cfe/trunk/www/cxx_status.html
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_
> status.html?rev=274049&r1=274048&r2=274049&view=diff
> ============================================================
> ==================
> --- cfe/trunk/www/cxx_status.html (original)
> +++ cfe/trunk/www/cxx_status.html Tue Jun 28 14:03:57 2016
> @@ -623,7 +623,7 @@ as the draft C++1z standard evolves.</p>
> <tr>
> <td>New specification for inheriting constructors (<a
> href="cxx_dr_status.html#1941">DR1941</a> et al)</td>
> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/
> 2015/p0136r1.html">P0136R1</a></td>
> - <td class="none" align="center">No</td>
> + <td class="svn" align="center">SVN <a href="p0136">(9)</a></td>
> </tr>
> <!-- Jacksonville papers -->
> <tr>
> @@ -735,6 +735,9 @@ all language versions that allow type de
> (per the request of the C++ committee).
> In Clang 3.7, a warning is emitted for all cases that would change
> meaning.
> </span>
> +<span id="p0136">(9): This is the resolution to a Defect Report, so is
> applied
> +to all language versions supporting inheriting constructors.
> +</span>
> </p>
>
> <h2 id="ts">Technical specifications and standing documents</h2>
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160923/ba1a7728/attachment-0001.html>
More information about the cfe-commits
mailing list