58 changes: 22 additions & 36 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1843,36 +1843,6 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
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,
Expand Down Expand Up @@ -2398,9 +2368,14 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
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
Expand Down Expand Up @@ -2443,18 +2418,23 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
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;

Expand Down Expand Up @@ -2485,6 +2465,12 @@ Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
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) {
NestedNameSpecifierLoc QualifierLoc
Expand Down
36 changes: 36 additions & 0 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -2690,6 +2690,16 @@ class TreeTransform {
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.
Expand Down Expand Up @@ -9937,6 +9947,32 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
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
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Serialization/ASTCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
case Decl::CXXDestructor:
case Decl::CXXConversion:
case Decl::UsingShadow:
case Decl::ConstructorUsingShadow:
case Decl::Var:
case Decl::FunctionTemplate:
case Decl::ClassTemplate:
Expand Down
38 changes: 34 additions & 4 deletions clang/lib/Serialization/ASTReaderDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -1421,6 +1422,16 @@ void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
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);
Expand Down Expand Up @@ -1768,11 +1779,17 @@ void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
}

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++];
}

Expand Down Expand Up @@ -2663,6 +2680,13 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
// 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());
}
Expand Down Expand Up @@ -3240,6 +3264,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
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;
Expand All @@ -3256,7 +3283,10 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
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);
Expand Down
12 changes: 12 additions & 0 deletions clang/lib/Serialization/ASTReaderStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,14 @@ void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) {
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);
Expand Down Expand Up @@ -3407,6 +3415,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
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;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
23 changes: 21 additions & 2 deletions clang/lib/Serialization/ASTWriterDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -1126,6 +1127,15 @@ void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) {
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());
Expand Down Expand Up @@ -1211,12 +1221,21 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
}

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) {
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Serialization/ASTWriterStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,15 @@ void ASTStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) {
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());
Expand Down
1 change: 1 addition & 0 deletions clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
// 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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,17 @@ namespace InhCtor {
int n = b.T(); // expected-error {{'T' is a protected member of 'InhCtor::A'}}
// expected-note@-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 {
Expand Down
42 changes: 42 additions & 0 deletions clang/test/CXX/basic/basic.types/p10.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
}
81 changes: 81 additions & 0 deletions clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p15.cpp
Original file line number Diff line number Diff line change
@@ -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}}
}
}
77 changes: 77 additions & 0 deletions clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p18.cpp
Original file line number Diff line number Diff line change
@@ -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"); }

}
28 changes: 27 additions & 1 deletion clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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@-3 {{refers to its own class}}
// expected-error@-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@-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;
}
}
25 changes: 25 additions & 0 deletions clang/test/CXX/drs/dr15xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
21 changes: 19 additions & 2 deletions clang/test/CXX/drs/dr16xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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]; };
Expand All @@ -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
}
52 changes: 48 additions & 4 deletions clang/test/CXX/drs/dr17xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(); };
Expand All @@ -30,5 +74,5 @@ namespace dr1758 { // dr1758: 3.7 c++11
operator A() { return A(); }
} b;
A a{b};
} // dr1758
#endif
}
111 changes: 107 additions & 4 deletions clang/test/CXX/drs/dr19xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand All @@ -54,33 +79,111 @@ 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
// FIXME: This diagnostic could be improved.
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
20 changes: 13 additions & 7 deletions clang/test/CXX/except/except.spec/p14.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>())), "");
}
66 changes: 34 additions & 32 deletions clang/test/CXX/special/class.inhctor/p1.cpp
Original file line number Diff line number Diff line change
@@ -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.

template<typename T> A(T, int = 0, ...); // expected-note 5{{here}}
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, 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> 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 {{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@-1 {{call to implicitly-deleted default constructor of 'B'}}
// expected-note@-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@-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@-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@-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@-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@-2 {{call to deleted constructor of 'B'}}
A a9{"foo"}; // expected-error {{ambiguous}}
B b9{"foo"}; // expected-error {{ambiguous}}

namespace PR15755 {
struct X {
Expand Down
58 changes: 35 additions & 23 deletions clang/test/CXX/special/class.inhctor/p2.cpp
Original file line number Diff line number Diff line change
@@ -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 {};

Expand All @@ -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>{} };
Expand All @@ -36,7 +39,7 @@ constexpr A a3ic = { X<3>{} }; // expected-error {{constructor is explicit}}


struct B : A {
using A::A; // expected-note 7{{here}}
using A::A;
};

B b0 { X<0>{} };
Expand All @@ -62,14 +65,19 @@ constexpr B b3ic = { X<3>{} }; // expected-error {{constructor is explicit}}

// '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 {
Expand All @@ -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 {};
Expand All @@ -116,6 +124,10 @@ constexpr UsingTemplateCtors uct4{ X<1>{}, 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}}
51 changes: 31 additions & 20 deletions clang/test/CXX/special/class.inhctor/p3.cpp
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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}}
25 changes: 14 additions & 11 deletions clang/test/CXX/special/class.inhctor/p4.cpp
Original file line number Diff line number Diff line change
@@ -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 {};

Expand All @@ -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) {}
Expand All @@ -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}}
Expand All @@ -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'}}
Expand All @@ -57,15 +60,15 @@ H h2("foo"); // expected-error {{call to deleted constructor of 'H'}}
// 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}}
}
49 changes: 25 additions & 24 deletions clang/test/CXX/special/class.inhctor/p7.cpp
Original file line number Diff line number Diff line change
@@ -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 B1 { // expected-note 2{{candidate}}
B1(int); // expected-note {{candidate}}
};
struct B2 {
B2(int); // expected-note {{conflicting constructor}}
struct B2 { // expected-note 2{{candidate}}
B2(int); // expected-note {{candidate}}
};
struct D1 : B1, B2 {
using B1::B1; // expected-note {{inherited here}}
using B2::B2; // expected-error {{already inherited constructor with the same signature}}
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}}
};
struct B6 {
template<typename T> B6(T); // expected-note {{conflicting constructor}}
template<typename T> B5(T);
};
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);
8 changes: 4 additions & 4 deletions clang/test/CXX/special/class.inhctor/p8.cpp
Original file line number Diff line number Diff line change
@@ -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) {}
Expand All @@ -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, "");
Expand All @@ -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'}}
124 changes: 124 additions & 0 deletions clang/test/CXX/special/class.init/class.inhctor.init/p1.cpp
Original file line number Diff line number Diff line change
@@ -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.
}
33 changes: 33 additions & 0 deletions clang/test/CXX/special/class.init/class.inhctor.init/p2.cpp
Original file line number Diff line number Diff line change
@@ -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
}
406 changes: 394 additions & 12 deletions clang/test/CodeGenCXX/inheriting-constructor.cpp

Large diffs are not rendered by default.

34 changes: 28 additions & 6 deletions clang/test/PCH/cxx11-inheriting-ctors.cpp
Original file line number Diff line number Diff line change
@@ -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) {}
Expand All @@ -27,7 +36,8 @@ struct Test3 : B {
using B::B;
};

#else
#elif !defined(HEADER2)
#define HEADER2

Test test1a(42);
Test test1b(nullptr);
Expand All @@ -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
37 changes: 37 additions & 0 deletions clang/test/SemaCXX/constant-expression-cxx11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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, "");
}
10 changes: 10 additions & 0 deletions clang/test/SemaCXX/cxx11-inheriting-ctors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
4 changes: 4 additions & 0 deletions clang/tools/libclang/CIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3955,6 +3955,9 @@ static const Decl *getDeclFromExpr(const Stmt *E) {
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();

Expand Down Expand Up @@ -5665,6 +5668,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
D->getLocation(), TU);

case Decl::UsingShadow:
case Decl::ConstructorUsingShadow:
return clang_getCursorDefinition(
MakeCXCursor(cast<UsingShadowDecl>(D)->getTargetDecl(),
TU));
Expand Down
1 change: 1 addition & 0 deletions clang/tools/libclang/CXCursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,7 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::CXXMemberCallExprClass:
case Stmt::CUDAKernelCallExprClass:
case Stmt::CXXConstructExprClass:
case Stmt::CXXInheritedCtorInitExprClass:
case Stmt::CXXTemporaryObjectExprClass:
case Stmt::CXXUnresolvedConstructExprClass:
case Stmt::UserDefinedLiteralClass:
Expand Down
5 changes: 4 additions & 1 deletion clang/www/cxx_status.html
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ <h2 id="cxx17">C++1z implementation status</h2>
<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>
Expand Down Expand Up @@ -735,6 +735,9 @@ <h2 id="cxx17">C++1z implementation status</h2>
(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>
Expand Down