summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/DeclCXX.h1
-rw-r--r--clang/include/clang/AST/Type.h3
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td26
-rw-r--r--clang/lib/AST/Type.cpp12
-rw-r--r--clang/lib/Sema/Sema.h25
-rw-r--r--clang/lib/Sema/SemaCXXCast.cpp5
-rw-r--r--clang/lib/Sema/SemaDecl.cpp34
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp23
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp20
-rw-r--r--clang/lib/Sema/SemaInit.cpp970
-rw-r--r--clang/lib/Sema/SemaInit.h530
-rw-r--r--clang/lib/Sema/SemaOverload.cpp26
-rw-r--r--clang/lib/Sema/SemaOverload.h21
-rw-r--r--clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp14
-rw-r--r--clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp3
-rw-r--r--clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp53
-rw-r--r--clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp129
-rw-r--r--clang/test/CodeGenCXX/references.cpp2
-rw-r--r--clang/test/SemaCXX/convert-to-bool.cpp6
-rw-r--r--clang/test/SemaCXX/decl-init-ref.cpp6
-rw-r--r--clang/test/SemaCXX/overloaded-operator.cpp2
-rw-r--r--clang/test/SemaCXX/ref-init-ambiguous.cpp7
-rw-r--r--clang/test/SemaCXX/references.cpp8
-rw-r--r--clang/test/SemaCXX/rval-references.cpp2
-rw-r--r--clang/test/SemaTemplate/instantiate-expr-4.cpp6
25 files changed, 1860 insertions, 74 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index a84efb18504..5507e99e45a 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -108,6 +108,7 @@ class CXXBaseSpecifier {
/// Range - The source code range that covers the full base
/// specifier, including the "virtual" (if present) and access
/// specifier (if present).
+ // FIXME: Move over to a TypeLoc!
SourceRange Range;
/// Virtual - Whether this is a virtual base class or not.
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 7b5598c4604..7c98403b6f5 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -813,8 +813,9 @@ public:
bool isBooleanType() const;
bool isCharType() const;
bool isWideCharType() const;
+ bool isAnyCharacterType() const;
bool isIntegralType() const;
-
+
/// Floating point categories.
bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double)
/// isComplexType() does *not* include complex integers (a GCC extension).
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6fadb00e1c9..d75c49b8992 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -445,6 +445,7 @@ def err_implicit_object_parameter_init : Error<
"of type %1">;
def note_field_decl : Note<"member is declared here">;
+def note_bitfield_decl : Note<"bit-field is declared here">;
def note_previous_decl : Note<
"%0 declared here">;
def note_member_synthesized_at : Note<
@@ -525,14 +526,31 @@ def err_lvalue_to_rvalue_ambig_ref : Error<"rvalue reference cannot bind to lval
def err_not_reference_to_const_init : Error<
"non-const lvalue reference to type %0 cannot be initialized "
"with a %1 of type %2">;
+def err_lvalue_reference_bind_to_temporary : Error<
+ "non-const lvalue reference to type %0 cannot bind to a temporary of type "
+ "%1">;
+def err_lvalue_reference_bind_to_unrelated : Error<
+ "non-const lvalue reference to type %0 cannot bind to a value of unrelated "
+ "type %1">;
+def err_reference_bind_drops_quals : Error<
+ "binding of reference to type %0 to a value of type %1 drops qualifiers">;
+def err_reference_bind_failed : Error<
+ "reference to type %0 could not bind to an %select{rvalue|lvalue}1 of type "
+ "%2">;
+
+
// FIXME: passing in an English string as %1!
def err_reference_init_drops_quals : Error<
"initialization of reference to type %0 with a %1 of type %2 drops "
"qualifiers">;
+def err_reference_bind_to_bitfield : Error<
+ "%select{non-const|volatile}0 reference cannot bind to bit-field %1">;
def err_reference_var_requires_init : Error<
"declaration of reference variable %0 requires an initializer">;
def err_const_var_requires_init : Error<
"declaration of const variable '%0' requires an initializer">;
+def err_reference_has_multiple_inits : Error<
+ "reference cannot be initialized with multiple values">;
def err_init_non_aggr_init_list : Error<
"initialization of non-aggregate type %0 with an initializer list">;
def err_init_reference_member_uninitialized : Error<
@@ -1575,6 +1593,9 @@ def warn_tentative_incomplete_array : Warning<
def err_typecheck_incomplete_array_needs_initializer : Error<
"definition of variable with array type needs an explicit size "
"or an initializer">;
+def err_array_init_not_init_list : Error<
+ "array initializater must be an initializer "
+ "list%select{| or string literal}0">;
def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">;
def err_typecheck_sclass_fscope : Error<
@@ -1861,7 +1882,10 @@ def err_typecheck_bool_condition : Error<
def err_typecheck_ambiguous_condition : Error<
"conversion from %0 to %1 is ambiguous">;
def err_typecheck_nonviable_condition : Error<
- "no viable conversion from %0 to %1 is possible">;
+ "no viable conversion from %0 to %1">;
+def err_typecheck_deleted_function : Error<
+ "conversion function from %0 to %1 invokes a deleted function">;
+
def err_expected_class_or_namespace : Error<"expected a class or namespace">;
def err_invalid_declarator_scope : Error<
"definition or redeclaration of %0 not in a namespace enclosing %1">;
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 70387c73a7f..687beaea08c 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -434,6 +434,18 @@ bool Type::isWideCharType() const {
return false;
}
+/// \brief Determine whether this type is any of the built-in character
+/// types.
+bool Type::isAnyCharacterType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return (BT->getKind() >= BuiltinType::Char_U &&
+ BT->getKind() <= BuiltinType::Char32) ||
+ (BT->getKind() >= BuiltinType::Char_S &&
+ BT->getKind() <= BuiltinType::WChar);
+
+ return false;
+}
+
/// isSignedIntegerType - Return true if this is an integer type that is
/// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
/// an enum decl which has a signed representation, or a vector of signed
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 6f47cd0bc95..ad903a0816b 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -95,7 +95,10 @@ namespace clang {
class CXXBasePaths;
class CXXTemporary;
class LookupResult;
-
+ class InitializedEntity;
+ class InitializationKind;
+ class InitializationSequence;
+
/// BlockSemaInfo - When a block is being parsed, this contains information
/// about the block. It is pointed to from Sema::CurBlock.
struct BlockSemaInfo {
@@ -812,16 +815,6 @@ public:
return NULL;
}
- /// OverloadingResult - Capture the result of performing overload
- /// resolution.
- enum OverloadingResult {
- OR_Success, ///< Overload resolution succeeded.
- OR_No_Viable_Function, ///< No viable function found.
- OR_Ambiguous, ///< Ambiguous candidates found.
- OR_Deleted ///< Overload resoltuion refers to a deleted function.
- };
-
-
/// Subroutines of ActOnDeclarator().
TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
TypeSourceInfo *TInfo);
@@ -1011,6 +1004,8 @@ public:
FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
bool Complain);
Expr *FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn);
+ OwningExprResult FixOverloadedFunctionReference(OwningExprResult,
+ FunctionDecl *Fn);
void AddOverloadedCallCandidates(llvm::SmallVectorImpl<NamedDecl*>& Callees,
DeclarationName &UnqualifiedName,
@@ -1854,14 +1849,6 @@ public:
/// it simply returns the passed in expression.
OwningExprResult MaybeBindToTemporary(Expr *E);
- /// InitializationKind - Represents which kind of C++ initialization
- /// [dcl.init] a routine is to perform.
- enum InitializationKind {
- IK_Direct, ///< Direct initialization
- IK_Copy, ///< Copy initialization
- IK_Default ///< Default initialization
- };
-
CXXConstructorDecl *
TryInitializationByConstructor(QualType ClassType,
Expr **Args, unsigned NumArgs,
diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp
index f9138902a67..857241d7148 100644
--- a/clang/lib/Sema/SemaCXXCast.cpp
+++ b/clang/lib/Sema/SemaCXXCast.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "SemaInit.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
@@ -864,7 +865,9 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
if (CXXConstructorDecl *Constructor
= Self.TryInitializationByConstructor(DestType, &SrcExpr, 1,
OpRange.getBegin(),
- Sema::IK_Direct)) {
+ InitializationKind::CreateDirect(OpRange.getBegin(),
+ OpRange.getBegin(),
+ OpRange.getEnd()))) {
ConversionDecl = Constructor;
Kind = CastExpr::CK_ConstructorConversion;
return TC_Success;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 96b6c16485c..bf6863bbf4b 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "SemaInit.h"
#include "Lookup.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTConsumer.h"
@@ -3486,8 +3487,35 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
VDecl->setInvalidDecl();
} else if (!VDecl->isInvalidDecl()) {
- if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
- VDecl->getDeclName(), DirectInit))
+ if (VDecl->getType()->isReferenceType()) {
+ InitializedEntity Entity
+ = InitializedEntity::InitializeVariable(VDecl);
+
+ // FIXME: Poor source location information.
+ InitializationKind Kind
+ = DirectInit? InitializationKind::CreateDirect(VDecl->getLocation(),
+ SourceLocation(),
+ SourceLocation())
+ : InitializationKind::CreateCopy(VDecl->getLocation(),
+ SourceLocation());
+ InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
+ if (InitSeq) {
+ OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, (void**)&Init, 1));
+ if (Result.isInvalid()) {
+ VDecl->setInvalidDecl();
+ return;
+ }
+
+ Init = Result.takeAs<Expr>();
+ } else {
+ InitSeq.Diagnose(*this, Entity, Kind, &Init, 1);
+ VDecl->setInvalidDecl();
+ return;
+ }
+
+ } else if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
+ VDecl->getDeclName(), DirectInit))
VDecl->setInvalidDecl();
// C++ 3.6.2p2, allow dynamic initialization of static initializers.
@@ -3677,7 +3705,7 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
SourceRange(Var->getLocation(),
Var->getLocation()),
Var->getDeclName(),
- IK_Default,
+ InitializationKind::CreateDefault(Var->getLocation()),
ConstructorArgs);
// FIXME: Location info for the variable initialization?
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 6f8a4f16d3b..d977ad6000d 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "SemaInit.h"
#include "Lookup.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@@ -1108,7 +1109,8 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
NumArgs),
IdLoc,
SourceRange(IdLoc, RParenLoc),
- Member->getDeclName(), IK_Direct,
+ Member->getDeclName(),
+ InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc),
ConstructorArgs);
if (C) {
@@ -1232,7 +1234,8 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
(void**)Args, NumArgs),
BaseLoc,
SourceRange(BaseLoc, RParenLoc),
- Name, IK_Direct,
+ Name,
+ InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc),
ConstructorArgs);
if (C) {
// Take over the constructor arguments as our own.
@@ -3656,7 +3659,9 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
SourceRange(VDecl->getLocation(),
RParenLoc),
VDecl->getDeclName(),
- IK_Direct,
+ InitializationKind::CreateDirect(VDecl->getLocation(),
+ LParenLoc,
+ RParenLoc),
ConstructorArgs);
if (!Constructor)
RealDecl->setInvalidDecl();
@@ -3692,7 +3697,7 @@ static void AddConstructorInitializationCandidates(Sema &SemaRef,
QualType ClassType,
Expr **Args,
unsigned NumArgs,
- Sema::InitializationKind Kind,
+ InitializationKind Kind,
OverloadCandidateSet &CandidateSet) {
// C++ [dcl.init]p14:
// If the initialization is direct-initialization, or if it is
@@ -3727,10 +3732,12 @@ static void AddConstructorInitializationCandidates(Sema &SemaRef,
else
Constructor = cast<CXXConstructorDecl>(*Con);
- if ((Kind == Sema::IK_Direct) ||
- (Kind == Sema::IK_Copy &&
+ if ((Kind.getKind() == InitializationKind::IK_Direct) ||
+ (Kind.getKind() == InitializationKind::IK_Value) ||
+ (Kind.getKind() == InitializationKind::IK_Copy &&
Constructor->isConvertingConstructor(/*AllowExplicit=*/false)) ||
- (Kind == Sema::IK_Default && Constructor->isDefaultConstructor())) {
+ ((Kind.getKind() == InitializationKind::IK_Default) &&
+ Constructor->isDefaultConstructor())) {
if (ConstructorTmpl)
SemaRef.AddTemplateOverloadCandidate(ConstructorTmpl,
/*ExplicitArgs*/ 0,
@@ -4002,7 +4009,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
// real, update the initializer with the resulting function.
if (!ICS) {
if (DiagnoseUseOfDecl(Fn, DeclLoc))
- return true;
+ return true;
Init = FixOverloadedFunctionReference(Init, Fn);
}
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 16c5275d7de..5e0ce666ea2 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "SemaInit.h"
#include "Lookup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
@@ -225,7 +226,9 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
SourceRange(TypeRange.getBegin(),
RParenLoc),
DeclarationName(),
- IK_Direct,
+ InitializationKind::CreateDirect(TypeRange.getBegin(),
+ LParenLoc,
+ RParenLoc),
ConstructorArgs);
if (!Constructor)
@@ -449,12 +452,17 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
// Skip all the checks.
} else if ((RT = AllocType->getAs<RecordType>()) &&
!AllocType->isAggregateType()) {
+ InitializationKind InitKind = InitializationKind::CreateDefault(TypeLoc);
+ if (NumConsArgs > 0)
+ InitKind = InitializationKind::CreateDirect(TypeLoc,
+ PlacementLParen,
+ PlacementRParen);
Constructor = PerformInitializationByConstructor(
AllocType, move(ConstructorArgs),
TypeLoc,
SourceRange(TypeLoc, ConstructorRParen),
RT->getDecl()->getDeclName(),
- NumConsArgs != 0 ? IK_Direct : IK_Default,
+ InitKind,
ConvertedConstructorArgs);
if (!Constructor)
return ExprError();
@@ -1584,7 +1592,7 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
OverloadCandidateSet::iterator Best;
switch (Self.BestViableFunction(CandidateSet, Loc, Best)) {
- case Sema::OR_Success:
+ case OR_Success:
// We found a match. Perform the conversions on the arguments and move on.
if (Self.PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0],
Best->Conversions[0], "converting") ||
@@ -1593,13 +1601,13 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
break;
return false;
- case Sema::OR_No_Viable_Function:
+ case OR_No_Viable_Function:
Self.Diag(Loc, diag::err_typecheck_cond_incompatible_operands)
<< LHS->getType() << RHS->getType()
<< LHS->getSourceRange() << RHS->getSourceRange();
return true;
- case Sema::OR_Ambiguous:
+ case OR_Ambiguous:
Self.Diag(Loc, diag::err_conditional_ambiguous_ovl)
<< LHS->getType() << RHS->getType()
<< LHS->getSourceRange() << RHS->getSourceRange();
@@ -1607,7 +1615,7 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
// the viable candidates.
break;
- case Sema::OR_Deleted:
+ case OR_Deleted:
assert(false && "Conditional operator has only built-in overloads");
break;
}
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 4b0fc84b301..d2ae906eff3 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -15,11 +15,13 @@
//
//===----------------------------------------------------------------------===//
+#include "SemaInit.h"
#include "Sema.h"
#include "clang/Parse/Designator.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "llvm/Support/ErrorHandling.h"
#include <map>
using namespace clang;
@@ -76,7 +78,7 @@ static bool CheckSingleInitializer(Expr *&Init, QualType DeclType,
OverloadCandidateSet CandidateSet;
if (S.IsUserDefinedConversion(Init, DeclType, ICS.UserDefined,
CandidateSet,
- true, false, false) != S.OR_Ambiguous)
+ true, false, false) != OR_Ambiguous)
return S.Diag(Init->getSourceRange().getBegin(),
diag::err_typecheck_convert_incompatible)
<< DeclType << Init->getType() << "initializing"
@@ -230,13 +232,20 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
+ // FIXME: Poor location information
+ InitializationKind InitKind
+ = InitializationKind::CreateCopy(Init->getLocStart(),
+ SourceLocation());
+ if (DirectInit)
+ InitKind = InitializationKind::CreateDirect(Init->getLocStart(),
+ SourceLocation(),
+ SourceLocation());
CXXConstructorDecl *Constructor
= PerformInitializationByConstructor(DeclType,
MultiExprArg(*this,
(void **)&Init, 1),
InitLoc, Init->getSourceRange(),
- InitEntity,
- DirectInit? IK_Direct : IK_Copy,
+ InitEntity, InitKind,
ConstructorArgs);
if (!Constructor)
return true;
@@ -1875,12 +1884,13 @@ bool Sema::CheckValueInitialization(QualType Type, SourceLocation Loc) {
if (ClassDecl->hasUserDeclaredConstructor()) {
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
+ // FIXME: Poor location information
CXXConstructorDecl *Constructor
= PerformInitializationByConstructor(Type,
MultiExprArg(*this, 0, 0),
Loc, SourceRange(Loc),
DeclarationName(),
- IK_Direct,
+ InitializationKind::CreateValue(Loc, Loc, Loc),
ConstructorArgs);
if (!Constructor)
return true;
@@ -1908,3 +1918,955 @@ bool Sema::CheckValueInitialization(QualType Type, SourceLocation Loc) {
return false;
}
+
+//===----------------------------------------------------------------------===//
+// Initialization entity
+//===----------------------------------------------------------------------===//
+
+void InitializedEntity::InitDeclLoc() {
+ assert((Kind == EK_Variable || Kind == EK_Parameter || Kind == EK_Member) &&
+ "InitDeclLoc cannot be used with non-declaration entities.");
+
+ if (TypeSourceInfo *DI = VariableOrMember->getTypeSourceInfo()) {
+ TL = DI->getTypeLoc();
+ return;
+ }
+
+ // FIXME: Once we've gone through the effort to create the fake
+ // TypeSourceInfo, should we cache it in the declaration?
+ // (If not, we "leak" it).
+ TypeSourceInfo *DI = VariableOrMember->getASTContext()
+ .CreateTypeSourceInfo(VariableOrMember->getType());
+ DI->getTypeLoc().initialize(VariableOrMember->getLocation());
+ TL = DI->getTypeLoc();
+}
+
+InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
+ CXXBaseSpecifier *Base)
+{
+ InitializedEntity Result;
+ Result.Kind = EK_Base;
+ Result.Base = Base;
+ // FIXME: CXXBaseSpecifier should store a TypeLoc.
+ TypeSourceInfo *DI = Context.CreateTypeSourceInfo(Base->getType());
+ DI->getTypeLoc().initialize(Base->getSourceRange().getBegin());
+ Result.TL = DI->getTypeLoc();
+ return Result;
+}
+
+//===----------------------------------------------------------------------===//
+// Initialization sequence
+//===----------------------------------------------------------------------===//
+
+void InitializationSequence::Step::Destroy() {
+ switch (Kind) {
+ case SK_ResolveAddressOfOverloadedFunction:
+ case SK_CastDerivedToBaseRValue:
+ case SK_CastDerivedToBaseLValue:
+ case SK_BindReference:
+ case SK_BindReferenceToTemporary:
+ case SK_UserConversion:
+ case SK_QualificationConversionRValue:
+ case SK_QualificationConversionLValue:
+ break;
+
+ case SK_ConversionSequence:
+ delete ICS;
+ }
+}
+
+void InitializationSequence::AddAddressOverloadResolutionStep(
+ FunctionDecl *Function) {
+ Step S;
+ S.Kind = SK_ResolveAddressOfOverloadedFunction;
+ S.Type = Function->getType();
+ S.Function = Function;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType,
+ bool IsLValue) {
+ Step S;
+ S.Kind = IsLValue? SK_CastDerivedToBaseLValue : SK_CastDerivedToBaseRValue;
+ S.Type = BaseType;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddReferenceBindingStep(QualType T,
+ bool BindingTemporary) {
+ Step S;
+ S.Kind = BindingTemporary? SK_BindReferenceToTemporary : SK_BindReference;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddUserConversionStep(FunctionDecl *Function) {
+ Step S;
+ S.Kind = SK_UserConversion;
+ S.Type = Function->getResultType().getNonReferenceType();
+ S.Function = Function;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddQualificationConversionStep(QualType Ty,
+ bool IsLValue) {
+ Step S;
+ S.Kind = IsLValue? SK_QualificationConversionLValue
+ : SK_QualificationConversionRValue;
+ S.Type = Ty;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddConversionSequenceStep(
+ const ImplicitConversionSequence &ICS,
+ QualType T) {
+ Step S;
+ S.Kind = SK_ConversionSequence;
+ S.Type = T;
+ S.ICS = new ImplicitConversionSequence(ICS);
+ Steps.push_back(S);
+}
+
+void InitializationSequence::SetOverloadFailure(FailureKind Failure,
+ OverloadingResult Result) {
+ SequenceKind = FailedSequence;
+ this->Failure = Failure;
+ this->FailedOverloadResult = Result;
+}
+
+//===----------------------------------------------------------------------===//
+// Attempt initialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Attempt list initialization (C++0x [dcl.init.list])
+static bool TryListInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ InitListExpr *InitList,
+ InitializationSequence &Sequence) {
+ // FIXME: For now, it is safe to assume that list initialization always
+ // works. When we actually perform list initialization, we'll do all of the
+ // necessary checking.
+ // C++0x initializer lists will force us to perform more checking here.
+ return true;
+}
+
+/// \brief Try a reference initialization that involves calling a conversion
+/// function.
+///
+/// FIXME: look intos DRs 656, 896
+static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr *Initializer,
+ bool AllowRValues,
+ InitializationSequence &Sequence) {
+ QualType DestType = Entity.getType().getType();
+ QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
+ QualType T1 = cv1T1.getUnqualifiedType();
+ QualType cv2T2 = Initializer->getType();
+ QualType T2 = cv2T2.getUnqualifiedType();
+
+ bool DerivedToBase;
+ assert(!S.CompareReferenceRelationship(Initializer->getLocStart(),
+ T1, T2, DerivedToBase) &&
+ "Must have incompatible references when binding via conversion");
+
+ // Build the candidate set directly in the initialization sequence
+ // structure, so that it will persist if we fail.
+ OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+ CandidateSet.clear();
+
+ // Determine whether we are allowed to call explicit constructors or
+ // explicit conversion operators.
+ bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct;
+
+ const RecordType *T1RecordType = 0;
+ if (AllowRValues && (T1RecordType = T1->getAs<RecordType>())) {
+ // The type we're converting to is a class type. Enumerate its constructors
+ // to see if there is a suitable conversion.
+ CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
+
+ DeclarationName ConstructorName
+ = S.Context.DeclarationNames.getCXXConstructorName(
+ S.Context.getCanonicalType(T1).getUnqualifiedType());
+ DeclContext::lookup_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = T1RecordDecl->lookup(ConstructorName);
+ Con != ConEnd; ++Con) {
+ // Find the constructor (which may be a template).
+ CXXConstructorDecl *Constructor = 0;
+ FunctionTemplateDecl *ConstructorTmpl
+ = dyn_cast<FunctionTemplateDecl>(*Con);
+ if (ConstructorTmpl)
+ Constructor = cast<CXXConstructorDecl>(
+ ConstructorTmpl->getTemplatedDecl());
+ else
+ Constructor = cast<CXXConstructorDecl>(*Con);
+
+ if (!Constructor->isInvalidDecl() &&
+ Constructor->isConvertingConstructor(AllowExplicit)) {
+ if (ConstructorTmpl)
+ S.AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0,
+ &Initializer, 1, CandidateSet);
+ else
+ S.AddOverloadCandidate(Constructor, &Initializer, 1, CandidateSet);
+ }
+ }
+ }
+
+ if (const RecordType *T2RecordType = T2->getAs<RecordType>()) {
+ // The type we're converting from is a class type, enumerate its conversion
+ // functions.
+ CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl());
+
+ // Determine the type we are converting to. If we are allowed to
+ // convert to an rvalue, take the type that the destination type
+ // refers to.
+ QualType ToType = AllowRValues? cv1T1 : DestType;
+
+ const UnresolvedSet *Conversions
+ = T2RecordDecl->getVisibleConversionFunctions();
+ for (UnresolvedSet::iterator I = Conversions->begin(),
+ E = Conversions->end();
+ I != E; ++I) {
+ NamedDecl *D = *I;
+ CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
+ CXXConversionDecl *Conv;
+ if (ConvTemplate)
+ Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+ else
+ Conv = cast<CXXConversionDecl>(*I);
+
+ // If the conversion function doesn't return a reference type,
+ // it can't be considered for this conversion unless we're allowed to
+ // consider rvalues.
+ // FIXME: Do we need to make sure that we only consider conversion
+ // candidates with reference-compatible results? That might be needed to
+ // break recursion.
+ if ((AllowExplicit || !Conv->isExplicit()) &&
+ (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){
+ if (ConvTemplate)
+ S.AddTemplateConversionCandidate(ConvTemplate, ActingDC, Initializer,
+ ToType, CandidateSet);
+ else
+ S.AddConversionCandidate(Conv, ActingDC, Initializer, cv1T1,
+ CandidateSet);
+ }
+ }
+ }
+
+ SourceLocation DeclLoc = Initializer->getLocStart();
+
+ // Perform overload resolution. If it fails, return the failed result.
+ OverloadCandidateSet::iterator Best;
+ if (OverloadingResult Result
+ = S.BestViableFunction(CandidateSet, DeclLoc, Best))
+ return Result;
+
+ // Add the user-defined conversion step.
+ FunctionDecl *Function = Best->Function;
+ Sequence.AddUserConversionStep(Function);
+
+ // Determine whether we need to perform derived-to-base or
+ // cv-qualification adjustments.
+ if (isa<CXXConversionDecl>(Function))
+ T2 = Function->getResultType();
+ else
+ T2 = cv1T1;
+
+ bool NewDerivedToBase = false;
+ Sema::ReferenceCompareResult NewRefRelationship
+ = S.CompareReferenceRelationship(DeclLoc, T1, T2.getNonReferenceType(),
+ NewDerivedToBase);
+ assert(NewRefRelationship != Sema::Ref_Incompatible &&
+ "Overload resolution picked a bad conversion function");
+ (void)NewRefRelationship;
+ if (NewDerivedToBase)
+ Sequence.AddDerivedToBaseCastStep(
+ S.Context.getQualifiedType(T1,
+ T2.getNonReferenceType().getQualifiers()),
+ /*isLValue=*/true);
+
+ if (cv1T1.getQualifiers() != T2.getNonReferenceType().getQualifiers())
+ Sequence.AddQualificationConversionStep(cv1T1, T2->isReferenceType());
+
+ Sequence.AddReferenceBindingStep(cv1T1, !T2->isReferenceType());
+ return OR_Success;
+}
+
+/// \brief Attempt reference initialization (C++0x [dcl.init.list])
+static void TryReferenceInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr *Initializer,
+ InitializationSequence &Sequence) {
+ Sequence.setSequenceKind(InitializationSequence::ReferenceBinding);
+
+ QualType DestType = Entity.getType().getType();
+ QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
+ QualType T1 = cv1T1.getUnqualifiedType();
+ QualType cv2T2 = Initializer->getType();
+ QualType T2 = cv2T2.getUnqualifiedType();
+ SourceLocation DeclLoc = Initializer->getLocStart();
+
+ // If the initializer is the address of an overloaded function, try
+ // to resolve the overloaded function. If all goes well, T2 is the
+ // type of the resulting function.
+ if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
+ FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Initializer,
+ T1,
+ false);
+ if (!Fn) {
+ Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+ return;
+ }
+
+ Sequence.AddAddressOverloadResolutionStep(Fn);
+ cv2T2 = Fn->getType();
+ T2 = cv2T2.getUnqualifiedType();
+ }
+
+ // FIXME: Rvalue references
+ bool ForceRValue = false;
+
+ // Compute some basic properties of the types and the initializer.
+ bool isLValueRef = DestType->isLValueReferenceType();
+ bool isRValueRef = !isLValueRef;
+ bool DerivedToBase = false;
+ Expr::isLvalueResult InitLvalue = ForceRValue ? Expr::LV_InvalidExpression :
+ Initializer->isLvalue(S.Context);
+ Sema::ReferenceCompareResult RefRelationship
+ = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase);
+
+ // C++0x [dcl.init.ref]p5:
+ // A reference to type "cv1 T1" is initialized by an expression of type
+ // "cv2 T2" as follows:
+ //
+ // - If the reference is an lvalue reference and the initializer
+ // expression
+ OverloadingResult ConvOvlResult = OR_Success;
+ if (isLValueRef) {
+ if (InitLvalue == Expr::LV_Valid &&
+ RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
+ // - is an lvalue (but is not a bit-field), and "cv1 T1" is
+ // reference-compatible with "cv2 T2," or
+ //
+ // Per C++ [over.best.ics]p2, we ignore whether the lvalue is a
+ // bit-field when we're determining whether the reference initialization
+ // can occur. This property will be checked by PerformInitialization.
+ if (DerivedToBase)
+ Sequence.AddDerivedToBaseCastStep(
+ S.Context.getQualifiedType(T1, cv2T2.getQualifiers()),
+ /*isLValue=*/true);
+ if (cv1T1.getQualifiers() != cv2T2.getQualifiers())
+ Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/true);
+ Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/false);
+ return;
+ }
+
+ // - has a class type (i.e., T2 is a class type), where T1 is not
+ // reference-related to T2, and can be implicitly converted to an
+ // lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible
+ // with "cv3 T3" (this conversion is selected by enumerating the
+ // applicable conversion functions (13.3.1.6) and choosing the best
+ // one through overload resolution (13.3)),
+ if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType()) {
+ ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, Kind,
+ Initializer,
+ /*AllowRValues=*/false,
+ Sequence);
+ if (ConvOvlResult == OR_Success)
+ return;
+ }
+ }
+
+ // - Otherwise, the reference shall be an lvalue reference to a
+ // non-volatile const type (i.e., cv1 shall be const), or the reference
+ // shall be an rvalue reference and the initializer expression shall
+ // be an rvalue.
+ if (!((isLValueRef && cv1T1.getCVRQualifiers() == Qualifiers::Const) ||
+ (isRValueRef && InitLvalue != Expr::LV_Valid))) {
+ if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
+ Sequence.SetOverloadFailure(
+ InitializationSequence::FK_ReferenceInitOverloadFailed,
+ ConvOvlResult);
+ else if (isLValueRef)
+ Sequence.SetFailed(InitLvalue == Expr::LV_Valid
+ ? (RefRelationship == Sema::Ref_Related
+ ? InitializationSequence::FK_ReferenceInitDropsQualifiers
+ : InitializationSequence::FK_NonConstLValueReferenceBindingToUnrelated)
+ : InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
+ else
+ Sequence.SetFailed(
+ InitializationSequence::FK_RValueReferenceBindingToLValue);
+
+ return;
+ }
+
+ // - If T1 and T2 are class types and
+ if (T1->isRecordType() && T2->isRecordType()) {
+ // - the initializer expression is an rvalue and "cv1 T1" is
+ // reference-compatible with "cv2 T2", or
+ if (InitLvalue != Expr::LV_Valid &&
+ RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
+ if (DerivedToBase)
+ Sequence.AddDerivedToBaseCastStep(
+ S.Context.getQualifiedType(T1, cv2T2.getQualifiers()),
+ /*isLValue=*/false);
+ if (cv1T1.getQualifiers() != cv2T2.getQualifiers())
+ Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/false);
+ Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
+ return;
+ }
+
+ // - T1 is not reference-related to T2 and the initializer expression
+ // can be implicitly converted to an rvalue of type "cv3 T3" (this
+ // conversion is selected by enumerating the applicable conversion
+ // functions (13.3.1.6) and choosing the best one through overload
+ // resolution (13.3)),
+ if (RefRelationship == Sema::Ref_Incompatible) {
+ ConvOvlResult = TryRefInitWithConversionFunction(S, Entity,
+ Kind, Initializer,
+ /*AllowRValues=*/true,
+ Sequence);
+ if (ConvOvlResult)
+ Sequence.SetOverloadFailure(
+ InitializationSequence::FK_ReferenceInitOverloadFailed,
+ ConvOvlResult);
+
+ return;
+ }
+
+ Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
+ return;
+ }
+
+ // - If the initializer expression is an rvalue, with T2 an array type,
+ // and "cv1 T1" is reference-compatible with "cv2 T2," the reference
+ // is bound to the object represented by the rvalue (see 3.10).
+ // FIXME: How can an array type be reference-compatible with anything?
+ // Don't we mean the element types of T1 and T2?
+
+ // - Otherwise, a temporary of type “cv1 T1” is created and initialized
+ // from the initializer expression using the rules for a non-reference
+ // copy initialization (8.5). The reference is then bound to the
+ // temporary. [...]
+ // Determine whether we are allowed to call explicit constructors or
+ // explicit conversion operators.
+ bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct);
+ ImplicitConversionSequence ICS
+ = S.TryImplicitConversion(Initializer, cv1T1,
+ /*SuppressUserConversions=*/false, AllowExplicit,
+ /*ForceRValue=*/false,
+ /*FIXME:InOverloadResolution=*/false,
+ /*UserCast=*/Kind.isExplicitCast());
+
+ if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion) {
+ // FIXME: Use the conversion function set stored in ICS to turn
+ // this into an overloading ambiguity diagnostic. However, we need
+ // to keep that set as an OverloadCandidateSet rather than as some
+ // other kind of set.
+ Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed);
+ return;
+ }
+
+ // [...] If T1 is reference-related to T2, cv1 must be the
+ // same cv-qualification as, or greater cv-qualification
+ // than, cv2; otherwise, the program is ill-formed.
+ if (RefRelationship == Sema::Ref_Related &&
+ !cv1T1.isAtLeastAsQualifiedAs(cv2T2)) {
+ Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
+ return;
+ }
+
+ // Perform the actual conversion.
+ Sequence.AddConversionSequenceStep(ICS, cv1T1);
+ Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
+ return;
+}
+
+/// \brief Attempt character array initialization from a string literal
+/// (C++ [dcl.init.string], C99 6.7.8).
+static void TryStringLiteralInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr *Initializer,
+ InitializationSequence &Sequence) {
+ // FIXME: Implement!
+}
+
+/// \brief Attempt value initialization (C++ [dcl.init]p7).
+static void TryValueInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ InitializationSequence &Sequence) {
+ // FIXME: Implement!
+}
+
+/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
+/// enumerates the constructors of the initialized entity and performs overload
+/// resolution to select the best.
+static void TryConstructorInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr **Args, unsigned NumArgs,
+ InitializationSequence &Sequence) {
+ // FIXME: Implement!
+}
+
+/// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]),
+/// which enumerates all conversion functions and performs overload resolution
+/// to select the best.
+static void TryUserDefinedConversion(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr *Initializer,
+ InitializationSequence &Sequence) {
+ // FIXME: Implement!
+}
+
+/// \brief Attempt an implicit conversion (C++ [conv]) converting from one
+/// non-class type to another.
+static void TryImplicitConversion(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr *Initializer,
+ InitializationSequence &Sequence) {
+ ImplicitConversionSequence ICS
+ = S.TryImplicitConversion(Initializer, Entity.getType().getType(),
+ /*SuppressUserConversions=*/true,
+ /*AllowExplicit=*/false,
+ /*ForceRValue=*/false,
+ /*FIXME:InOverloadResolution=*/false,
+ /*UserCast=*/Kind.isExplicitCast());
+
+ if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion) {
+ Sequence.SetFailed(InitializationSequence::FK_ConversionFailed);
+ return;
+ }
+
+ Sequence.AddConversionSequenceStep(ICS, Entity.getType().getType());
+}
+
+InitializationSequence::InitializationSequence(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr **Args,
+ unsigned NumArgs) {
+ ASTContext &Context = S.Context;
+
+ // C++0x [dcl.init]p16:
+ // The semantics of initializers are as follows. The destination type is
+ // the type of the object or reference being initialized and the source
+ // type is the type of the initializer expression. The source type is not
+ // defined when the initializer is a braced-init-list or when it is a
+ // parenthesized list of expressions.
+ QualType DestType = Entity.getType().getType();
+
+ if (DestType->isDependentType() ||
+ Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
+ SequenceKind = DependentSequence;
+ return;
+ }
+
+ QualType SourceType;
+ Expr *Initializer = 0;
+ if (Kind.getKind() == InitializationKind::IK_Copy) {
+ Initializer = Args[0];
+ if (!isa<InitListExpr>(Initializer))
+ SourceType = Initializer->getType();
+ }
+
+ // - If the initializer is a braced-init-list, the object is
+ // list-initialized (8.5.4).
+ if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) {
+ TryListInitialization(S, Entity, Kind, InitList, *this);
+ }
+
+ // - If the destination type is a reference type, see 8.5.3.
+ if (DestType->isReferenceType()) {
+ // C++0x [dcl.init.ref]p1:
+ // A variable declared to be a T& or T&&, that is, "reference to type T"
+ // (8.3.2), shall be initialized by an object, or function, of type T or
+ // by an object that can be converted into a T.
+ // (Therefore, multiple arguments are not permitted.)
+ if (NumArgs != 1)
+ SetFailed(FK_TooManyInitsForReference);
+ else
+ TryReferenceInitialization(S, Entity, Kind, Args[0], *this);
+ return;
+ }
+
+ // - If the destination type is an array of characters, an array of
+ // char16_t, an array of char32_t, or an array of wchar_t, and the
+ // initializer is a string literal, see 8.5.2.
+ if (Initializer && IsStringInit(Initializer, DestType, Context)) {
+ TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
+ return;
+ }
+
+ // - If the initializer is (), the object is value-initialized.
+ if (Kind.getKind() == InitializationKind::IK_Value) {
+ TryValueInitialization(S, Entity, Kind, *this);
+ return;
+ }
+
+ // - Otherwise, if the destination type is an array, the program is
+ // ill-formed.
+ if (const ArrayType *AT = Context.getAsArrayType(DestType)) {
+ if (AT->getElementType()->isAnyCharacterType())
+ SetFailed(FK_ArrayNeedsInitListOrStringLiteral);
+ else
+ SetFailed(FK_ArrayNeedsInitList);
+
+ return;
+ }
+
+ // - If the destination type is a (possibly cv-qualified) class type:
+ if (DestType->isRecordType()) {
+ // - If the initialization is direct-initialization, or if it is
+ // copy-initialization where the cv-unqualified version of the
+ // source type is the same class as, or a derived class of, the
+ // class of the destination, constructors are considered. [...]
+ if (Kind.getKind() == InitializationKind::IK_Direct ||
+ (Kind.getKind() == InitializationKind::IK_Copy &&
+ (Context.hasSameUnqualifiedType(SourceType, DestType) ||
+ S.IsDerivedFrom(SourceType, DestType))))
+ TryConstructorInitialization(S, Entity, Kind, Args, NumArgs, *this);
+ // - Otherwise (i.e., for the remaining copy-initialization cases),
+ // user-defined conversion sequences that can convert from the source
+ // type to the destination type or (when a conversion function is
+ // used) to a derived class thereof are enumerated as described in
+ // 13.3.1.4, and the best one is chosen through overload resolution
+ // (13.3).
+ else
+ TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
+ return;
+ }
+
+ // - Otherwise, if the source type is a (possibly cv-qualified) class
+ // type, conversion functions are considered.
+ if (SourceType->isRecordType()) {
+ TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
+ return;
+ }
+
+ // - Otherwise, the initial value of the object being initialized is the
+ // (possibly converted) value of the ini- tializer expression. Standard
+ // conversions (Clause 4) will be used, if necessary, to convert the
+ // initializer expression to the cv-unqualified version of the
+ // destination type; no user-defined conversions are considered.
+ TryImplicitConversion(S, Entity, Kind, Initializer, *this);
+}
+
+InitializationSequence::~InitializationSequence() {
+ for (llvm::SmallVectorImpl<Step>::iterator Step = Steps.begin(),
+ StepEnd = Steps.end();
+ Step != StepEnd; ++Step)
+ Step->Destroy();
+}
+
+//===----------------------------------------------------------------------===//
+// Perform initialization
+//===----------------------------------------------------------------------===//
+
+Action::OwningExprResult
+InitializationSequence::Perform(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Action::MultiExprArg Args) {
+ if (SequenceKind == FailedSequence) {
+ unsigned NumArgs = Args.size();
+ Diagnose(S, Entity, Kind, (Expr **)Args.release(), NumArgs);
+ return S.ExprError();
+ }
+
+ if (SequenceKind == DependentSequence) {
+ if (Kind.getKind() == InitializationKind::IK_Copy)
+ return Sema::OwningExprResult(S, Args.release()[0]);
+
+ unsigned NumArgs = Args.size();
+ return S.Owned(new (S.Context) ParenListExpr(S.Context,
+ SourceLocation(),
+ (Expr **)Args.release(),
+ NumArgs,
+ SourceLocation()));
+ }
+
+ QualType DestType = Entity.getType().getType().getNonReferenceType();
+
+ Sema::OwningExprResult CurInit(S);
+ // For copy initialization and any other initialization forms that
+ // only have a single initializer, we start with the (only)
+ // initializer we have.
+ // FIXME: DPG is not happy about this. There's confusion regarding whether
+ // we're supposed to start the conversion from the solitary initializer or
+ // from the set of arguments.
+ if (Kind.getKind() == InitializationKind::IK_Copy ||
+ SequenceKind == ReferenceBinding) {
+ assert(Args.size() == 1);
+ CurInit = Sema::OwningExprResult(S, Args.release()[0]);
+ if (CurInit.isInvalid())
+ return S.ExprError();
+ }
+
+ // Walk through the computed steps for the initialization sequence,
+ // performing the specified conversions along the way.
+ for (step_iterator Step = step_begin(), StepEnd = step_end();
+ Step != StepEnd; ++Step) {
+ if (CurInit.isInvalid())
+ return S.ExprError();
+
+ Expr *CurInitExpr = (Expr *)CurInit.get();
+ QualType SourceType = CurInitExpr->getType();
+
+ switch (Step->Kind) {
+ case SK_ResolveAddressOfOverloadedFunction:
+ // Overload resolution determined which function invoke; update the
+ // initializer to reflect that choice.
+ CurInit = S.FixOverloadedFunctionReference(move(CurInit), Step->Function);
+ break;
+
+ case SK_CastDerivedToBaseRValue:
+ case SK_CastDerivedToBaseLValue: {
+ // We have a derived-to-base cast that produces either an rvalue or an
+ // lvalue. Perform that cast.
+
+ // Casts to inaccessible base classes are allowed with C-style casts.
+ bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast();
+ if (S.CheckDerivedToBaseConversion(SourceType, Step->Type,
+ CurInitExpr->getLocStart(),
+ CurInitExpr->getSourceRange(),
+ IgnoreBaseAccess))
+ return S.ExprError();
+
+ CurInit = S.Owned(new (S.Context) ImplicitCastExpr(Step->Type,
+ CastExpr::CK_DerivedToBase,
+ (Expr*)CurInit.release(),
+ Step->Kind == SK_CastDerivedToBaseLValue));
+ break;
+ }
+
+ case SK_BindReference:
+ if (FieldDecl *BitField = CurInitExpr->getBitField()) {
+ // References cannot bind to bit fields (C++ [dcl.init.ref]p5).
+ S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield)
+ << Entity.getType().getType().isVolatileQualified()
+ << BitField->getDeclName()
+ << CurInitExpr->getSourceRange();
+ S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
+ return S.ExprError();
+ }
+
+ // Reference binding does not have any corresponding ASTs.
+
+ // Check exception specifications
+ if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType))
+ return S.ExprError();
+ break;
+
+ case SK_BindReferenceToTemporary:
+ // Check exception specifications
+ if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType))
+ return S.ExprError();
+
+ // FIXME: At present, we have no AST to describe when we need to make a
+ // temporary to bind a reference to. We should.
+ break;
+
+ case SK_UserConversion: {
+ // We have a user-defined conversion that invokes either a constructor
+ // or a conversion function.
+ CastExpr::CastKind CastKind = CastExpr::CK_Unknown;
+ if (CXXConstructorDecl *Constructor
+ = dyn_cast<CXXConstructorDecl>(Step->Function)) {
+ // Build a call to the selected constructor.
+ ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
+ SourceLocation Loc = CurInitExpr->getLocStart();
+ CurInit.release(); // Ownership transferred into MultiExprArg, below.
+
+ // Determine the arguments required to actually perform the constructor
+ // call.
+ if (S.CompleteConstructorCall(Constructor,
+ Sema::MultiExprArg(S,
+ (void **)&CurInitExpr,
+ 1),
+ Loc, ConstructorArgs))
+ return S.ExprError();
+
+ // Build the an expression that constructs a temporary.
+ CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor,
+ move_arg(ConstructorArgs));
+ if (CurInit.isInvalid())
+ return S.ExprError();
+
+ CastKind = CastExpr::CK_ConstructorConversion;
+ } else {
+ // Build a call to the conversion function.
+ CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Step->Function);
+
+ // FIXME: Should we move this initialization into a separate
+ // derived-to-base conversion? I believe the answer is "no", because
+ // we don't want to turn off access control here for c-style casts.
+ if (S.PerformObjectArgumentInitialization(CurInitExpr, Conversion))
+ return S.ExprError();
+
+ // Do a little dance to make sure that CurInit has the proper
+ // pointer.
+ CurInit.release();
+
+ // Build the actual call to the conversion function.
+ CurInit = S.Owned(S.BuildCXXMemberCallExpr(CurInitExpr, Conversion));
+ if (CurInit.isInvalid() || !CurInit.get())
+ return S.ExprError();
+
+ CastKind = CastExpr::CK_UserDefinedConversion;
+ }
+
+ CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+ CurInitExpr = CurInit.takeAs<Expr>();
+ CurInit = S.Owned(new (S.Context) ImplicitCastExpr(CurInitExpr->getType(),
+ CastKind,
+ CurInitExpr,
+ false));
+ break;
+ }
+
+ case SK_QualificationConversionLValue:
+ case SK_QualificationConversionRValue:
+ // Perform a qualification conversion; these can never go wrong.
+ S.ImpCastExprToType(CurInitExpr, Step->Type,
+ CastExpr::CK_NoOp,
+ Step->Kind == SK_QualificationConversionLValue);
+ CurInit.release();
+ CurInit = S.Owned(CurInitExpr);
+ break;
+
+ case SK_ConversionSequence:
+ if (S.PerformImplicitConversion(CurInitExpr, Step->Type, "converting",
+ false, false, *Step->ICS))
+ return S.ExprError();
+
+ CurInit.release();
+ CurInit = S.Owned(CurInitExpr);
+ break;
+ }
+ }
+
+ return move(CurInit);
+}
+
+//===----------------------------------------------------------------------===//
+// Diagnose initialization failures
+//===----------------------------------------------------------------------===//
+bool InitializationSequence::Diagnose(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr **Args, unsigned NumArgs) {
+ if (SequenceKind != FailedSequence)
+ return false;
+
+ QualType DestType = Entity.getType().getType();
+ switch (Failure) {
+ case FK_TooManyInitsForReference:
+ S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
+ << SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
+ break;
+
+ case FK_ArrayNeedsInitList:
+ case FK_ArrayNeedsInitListOrStringLiteral:
+ S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list)
+ << (Failure == FK_ArrayNeedsInitListOrStringLiteral);
+ break;
+
+ case FK_AddressOfOverloadFailed:
+ S.ResolveAddressOfOverloadedFunction(Args[0],
+ DestType.getNonReferenceType(),
+ true);
+ break;
+
+ case FK_ReferenceInitOverloadFailed:
+ switch (FailedOverloadResult) {
+ case OR_Ambiguous:
+ S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition)
+ << Args[0]->getType() << DestType.getNonReferenceType()
+ << Args[0]->getSourceRange();
+ S.PrintOverloadCandidates(FailedCandidateSet, true);
+ break;
+
+ case OR_No_Viable_Function:
+ S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
+ << Args[0]->getType() << DestType.getNonReferenceType()
+ << Args[0]->getSourceRange();
+ S.PrintOverloadCandidates(FailedCandidateSet, false);
+ break;
+
+ case OR_Deleted: {
+ S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
+ << Args[0]->getType() << DestType.getNonReferenceType()
+ << Args[0]->getSourceRange();
+ OverloadCandidateSet::iterator Best;
+ OverloadingResult Ovl = S.BestViableFunction(FailedCandidateSet,
+ Kind.getLocation(),
+ Best);
+ if (Ovl == OR_Deleted) {
+ S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
+ << Best->Function->isDeleted();
+ } else {
+ llvm::llvm_unreachable("Inconsistent overload resolution?");
+ }
+ break;
+ }
+
+ case OR_Success:
+ llvm::llvm_unreachable("Conversion did not fail!");
+ break;
+ }
+ break;
+
+ case FK_NonConstLValueReferenceBindingToTemporary:
+ case FK_NonConstLValueReferenceBindingToUnrelated:
+ S.Diag(Kind.getLocation(),
+ Failure == FK_NonConstLValueReferenceBindingToTemporary
+ ? diag::err_lvalue_reference_bind_to_temporary
+ : diag::err_lvalue_reference_bind_to_unrelated)
+ << DestType.getNonReferenceType()
+ << Args[0]->getType()
+ << Args[0]->getSourceRange();
+ break;
+
+ case FK_RValueReferenceBindingToLValue:
+ S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref)
+ << Args[0]->getSourceRange();
+ break;
+
+ case FK_ReferenceInitDropsQualifiers:
+ S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
+ << DestType.getNonReferenceType()
+ << Args[0]->getType()
+ << Args[0]->getSourceRange();
+ break;
+
+ case FK_ReferenceInitFailed:
+ S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
+ << DestType.getNonReferenceType()
+ << (Args[0]->isLvalue(S.Context) == Expr::LV_Valid)
+ << Args[0]->getType()
+ << Args[0]->getSourceRange();
+ break;
+
+ case FK_ConversionFailed:
+ S.Diag(Kind.getLocation(), diag::err_cannot_initialize_decl_noname)
+ << DestType
+ << (Args[0]->isLvalue(S.Context) == Expr::LV_Valid)
+ << Args[0]->getType()
+ << Args[0]->getSourceRange();
+ break;
+ }
+
+ return true;
+}
diff --git a/clang/lib/Sema/SemaInit.h b/clang/lib/Sema/SemaInit.h
index e69de29bb2d..85aa421db67 100644
--- a/clang/lib/Sema/SemaInit.h
+++ b/clang/lib/Sema/SemaInit.h
@@ -0,0 +1,530 @@
+//===--- SemaInit.h - Semantic Analysis for Initializers ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides supporting data types for initialization of objects.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_INIT_H
+#define LLVM_CLANG_SEMA_INIT_H
+
+#include "SemaOverload.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Parse/Action.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+
+namespace clang {
+
+class CXXBaseSpecifier;
+class DeclaratorDecl;
+class DeclaratorInfo;
+class FieldDecl;
+class FunctionDecl;
+class ParmVarDecl;
+class Sema;
+class TypeLoc;
+class VarDecl;
+
+/// \brief Describes an entity that is being initialized.
+class InitializedEntity {
+public:
+ /// \brief Specifies the kind of entity being initialized.
+ enum EntityKind {
+ /// \brief The entity being initialized is a variable.
+ EK_Variable,
+ /// \brief The entity being initialized is a function parameter.
+ EK_Parameter,
+ /// \brief The entity being initialized is the result of a function call.
+ EK_Result,
+ /// \brief The entity being initialized is an exception object that
+ /// is being thrown.
+ EK_Exception,
+ /// \brief The entity being initialized is a temporary object.
+ EK_Temporary,
+ /// \brief The entity being initialized is a base member subobject.
+ EK_Base,
+ /// \brief The entity being initialized is a non-static data member
+ /// subobject.
+ EK_Member
+ };
+
+private:
+ /// \brief The kind of entity being initialized.
+ EntityKind Kind;
+
+ /// \brief The type of the object or reference being initialized along with
+ /// its location information.
+ TypeLoc TL;
+
+ union {
+ /// \brief When Kind == EK_Variable, EK_Parameter, or EK_Member,
+ /// the VarDecl, ParmVarDecl, or FieldDecl, respectively.
+ DeclaratorDecl *VariableOrMember;
+
+ /// \brief When Kind == EK_Result or EK_Exception, the location of the
+ /// 'return' or 'throw' keyword, respectively. When Kind == EK_Temporary,
+ /// the location where the temporary is being created.
+ unsigned Location;
+
+ /// \brief When Kind == EK_Base, the base specifier that provides the
+ /// base class.
+ CXXBaseSpecifier *Base;
+ };
+
+ InitializedEntity() { }
+
+ /// \brief Create the initialization entity for a variable.
+ InitializedEntity(VarDecl *Var)
+ : Kind(EK_Variable),
+ VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Var))
+ {
+ InitDeclLoc();
+ }
+
+ /// \brief Create the initialization entity for a parameter.
+ InitializedEntity(ParmVarDecl *Parm)
+ : Kind(EK_Parameter),
+ VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Parm))
+ {
+ InitDeclLoc();
+ }
+
+ /// \brief Create the initialization entity for the result of a function,
+ /// throwing an object, or performing an explicit cast.
+ InitializedEntity(EntityKind Kind, SourceLocation Loc, TypeLoc TL)
+ : Kind(Kind), TL(TL), Location(Loc.getRawEncoding()) { }
+
+ /// \brief Create the initialization entity for a member subobject.
+ InitializedEntity(FieldDecl *Member)
+ : Kind(EK_Member),
+ VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Member))
+ {
+ InitDeclLoc();
+ }
+
+ /// \brief Initialize type-location information from a declaration.
+ void InitDeclLoc();
+
+public:
+ /// \brief Create the initialization entity for a variable.
+ static InitializedEntity InitializeVariable(VarDecl *Var) {
+ return InitializedEntity(Var);
+ }
+
+ /// \brief Create the initialization entity for a parameter.
+ static InitializedEntity InitializeParameter(ParmVarDecl *Parm) {
+ return InitializedEntity(Parm);
+ }
+
+ /// \brief Create the initialization entity for the result of a function.
+ static InitializedEntity InitializeResult(SourceLocation ReturnLoc,
+ TypeLoc TL) {
+ return InitializedEntity(EK_Result, ReturnLoc, TL);
+ }
+
+ /// \brief Create the initialization entity for an exception object.
+ static InitializedEntity InitializeException(SourceLocation ThrowLoc,
+ TypeLoc TL) {
+ return InitializedEntity(EK_Exception, ThrowLoc, TL);
+ }
+
+ /// \brief Create the initialization entity for a temporary.
+ static InitializedEntity InitializeTemporary(EntityKind Kind, TypeLoc TL) {
+ return InitializedEntity(Kind, SourceLocation(), TL);
+ }
+
+ /// \brief Create the initialization entity for a base class subobject.
+ static InitializedEntity InitializeBase(ASTContext &Context,
+ CXXBaseSpecifier *Base);
+
+ /// \brief Create the initialize entity for a member subobject.
+ static InitializedEntity InitializeMember(FieldDecl *Member) {
+ return InitializedEntity(Member);
+ }
+
+ /// \brief Determine the kind of initialization.
+ EntityKind getKind() const { return Kind; }
+
+ /// \brief Retrieve type being initialized.
+ TypeLoc getType() const { return TL; }
+
+ /// \brief Determine the location of the 'return' keyword when initializing
+ /// the result of a function call.
+ SourceLocation getReturnLoc() const {
+ assert(getKind() == EK_Result && "No 'return' location!");
+ return SourceLocation::getFromRawEncoding(Location);
+ }
+
+ /// \brief Determine the location of the 'throw' keyword when initializing
+ /// an exception object.
+ SourceLocation getThrowLoc() const {
+ assert(getKind() == EK_Exception && "No 'throw' location!");
+ return SourceLocation::getFromRawEncoding(Location);
+ }
+};
+
+/// \brief Describes the kind of initialization being performed, along with
+/// location information for tokens related to the initialization (equal sign,
+/// parentheses).
+class InitializationKind {
+public:
+ /// \brief The kind of initialization being performed.
+ enum InitKind {
+ IK_Direct, ///< Direct initialization
+ IK_Copy, ///< Copy initialization
+ IK_Default, ///< Default initialization
+ IK_Value ///< Value initialization
+ };
+
+private:
+ /// \brief The kind of initialization that we're storing.
+ enum StoredInitKind {
+ SIK_Direct = IK_Direct, ///< Direct initialization
+ SIK_Copy = IK_Copy, ///< Copy initialization
+ SIK_Default = IK_Default, ///< Default initialization
+ SIK_Value = IK_Value, ///< Value initialization
+ SIK_DirectCast, ///< Direct initialization due to a cast
+ /// \brief Direct initialization due to a C-style or functional cast.
+ SIK_DirectCStyleOrFunctionalCast
+ };
+
+ /// \brief The kind of initialization being performed.
+ StoredInitKind Kind;
+
+ /// \brief The source locations involved in the initialization.
+ SourceLocation Locations[3];
+
+ InitializationKind(StoredInitKind Kind, SourceLocation Loc1,
+ SourceLocation Loc2, SourceLocation Loc3)
+ : Kind(Kind)
+ {
+ Locations[0] = Loc1;
+ Locations[1] = Loc2;
+ Locations[2] = Loc3;
+ }
+
+public:
+ /// \brief Create a direct initialization.
+ static InitializationKind CreateDirect(SourceLocation InitLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ return InitializationKind(SIK_Direct, InitLoc, LParenLoc, RParenLoc);
+ }
+
+ /// \brief Create a direct initialization due to a cast.
+ static InitializationKind CreateCast(SourceRange TypeRange,
+ bool IsCStyleCast) {
+ return InitializationKind(IsCStyleCast? SIK_DirectCStyleOrFunctionalCast
+ : SIK_DirectCast,
+ TypeRange.getBegin(), TypeRange.getBegin(),
+ TypeRange.getEnd());
+ }
+
+ /// \brief Create a copy initialization.
+ static InitializationKind CreateCopy(SourceLocation InitLoc,
+ SourceLocation EqualLoc) {
+ return InitializationKind(SIK_Copy, InitLoc, EqualLoc, EqualLoc);
+ }
+
+ /// \brief Create a default initialization.
+ static InitializationKind CreateDefault(SourceLocation InitLoc) {
+ return InitializationKind(SIK_Default, InitLoc, InitLoc, InitLoc);
+ }
+
+ /// \brief Create a value initialization.
+ static InitializationKind CreateValue(SourceLocation InitLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ return InitializationKind(SIK_Value, InitLoc, LParenLoc, RParenLoc);
+ }
+
+ /// \brief Determine the initialization kind.
+ InitKind getKind() const {
+ if (Kind > SIK_Value)
+ return IK_Direct;
+
+ return (InitKind)Kind;
+ }
+
+ /// \brief Determine whether this initialization is an explicit cast.
+ bool isExplicitCast() const {
+ return Kind == SIK_DirectCast || Kind == SIK_DirectCStyleOrFunctionalCast;
+ }
+
+ /// \brief Determine whether this initialization is a C-style cast.
+ bool isCStyleOrFunctionalCast() const {
+ return Kind == SIK_DirectCStyleOrFunctionalCast;
+ }
+
+ /// \brief Retrieve the location at which initialization is occurring.
+ SourceLocation getLocation() const { return Locations[0]; }
+
+ /// \brief Retrieve the source range that covers the initialization.
+ SourceRange getRange() const {
+ return SourceRange(Locations[0], Locations[1]);
+ }
+
+ /// \brief Retrieve the location of the equal sign for copy initialization
+ /// (if present).
+ SourceLocation getEqualLoc() const {
+ assert(Kind == SIK_Copy && "Only copy initialization has an '='");
+ return Locations[1];
+ }
+
+ /// \brief Retrieve the source range containing the locations of the open
+ /// and closing parentheses for value and direct initializations.
+ SourceRange getParenRange() const {
+ assert((getKind() == IK_Direct || Kind == SIK_Value) &&
+ "Only direct- and value-initialization have parentheses");
+ return SourceRange(Locations[1], Locations[2]);
+ }
+};
+
+/// \brief Describes the sequence of initializations required to initialize
+/// a given object or reference with a set of arguments.
+class InitializationSequence {
+public:
+ /// \brief Describes the kind of initialization sequence computed.
+ enum SequenceKind {
+ /// \brief A failed initialization sequence. The failure kind tells what
+ /// happened.
+ FailedSequence = 0,
+
+ /// \brief A dependent initialization, which could not be
+ /// type-checked due to the presence of dependent types or
+ /// dependently-type expressions.
+ DependentSequence,
+
+ /// \brief A reference binding.
+ ReferenceBinding
+ };
+
+ /// \brief Describes the kind of a particular step in an initialization
+ /// sequence.
+ enum StepKind {
+ /// \brief Resolve the address of an overloaded function to a specific
+ /// function declaration.
+ SK_ResolveAddressOfOverloadedFunction,
+ /// \brief Perform a derived-to-base cast, producing an rvalue.
+ SK_CastDerivedToBaseRValue,
+ /// \brief Perform a derived-to-base cast, producing an lvalue.
+ SK_CastDerivedToBaseLValue,
+ /// \brief Reference binding to an lvalue.
+ SK_BindReference,
+ /// \brief Reference binding to a temporary.
+ SK_BindReferenceToTemporary,
+ /// \brief Perform a user-defined conversion, either via a conversion
+ /// function or via a constructor.
+ SK_UserConversion,
+ /// \brief Perform a qualification conversion, producing an rvalue.
+ SK_QualificationConversionRValue,
+ /// \brief Perform a qualification conversion, producing an lvalue.
+ SK_QualificationConversionLValue,
+ /// \brief Perform an implicit conversion sequence.
+ SK_ConversionSequence
+ };
+
+ /// \brief A single step in the initialization sequence.
+ class Step {
+ public:
+ /// \brief The kind of conversion or initialization step we are taking.
+ StepKind Kind;
+
+ // \brief The type that results from this initialization.
+ QualType Type;
+
+ union {
+ /// \brief When Kind == SK_ResolvedOverloadedFunction or Kind ==
+ /// SK_UserConversion, the function that the expression should be
+ /// resolved to or the conversion function to call, respectively.
+ FunctionDecl *Function;
+
+ /// \brief When Kind = SK_ConversionSequence, the implicit conversion
+ /// sequence
+ ImplicitConversionSequence *ICS;
+ };
+
+ void Destroy();
+ };
+
+private:
+ /// \brief The kind of initialization sequence computed.
+ enum SequenceKind SequenceKind;
+
+ /// \brief Steps taken by this initialization.
+ llvm::SmallVector<Step, 4> Steps;
+
+public:
+ /// \brief Describes why initialization failed.
+ enum FailureKind {
+ /// \brief Too many initializers provided for a reference.
+ FK_TooManyInitsForReference,
+ /// \brief Array must be initialized with an initializer list.
+ FK_ArrayNeedsInitList,
+ /// \brief Array must be initialized with an initializer list or a
+ /// string literal.
+ FK_ArrayNeedsInitListOrStringLiteral,
+ /// \brief Cannot resolve the address of an overloaded function.
+ FK_AddressOfOverloadFailed,
+ /// \brief Overloading due to reference initialization failed.
+ FK_ReferenceInitOverloadFailed,
+ /// \brief Non-const lvalue reference binding to a temporary.
+ FK_NonConstLValueReferenceBindingToTemporary,
+ /// \brief Non-const lvalue reference binding to an lvalue of unrelated
+ /// type.
+ FK_NonConstLValueReferenceBindingToUnrelated,
+ /// \brief Rvalue reference binding to an lvalue.
+ FK_RValueReferenceBindingToLValue,
+ /// \brief Reference binding drops qualifiers.
+ FK_ReferenceInitDropsQualifiers,
+ /// \brief Reference binding failed.
+ FK_ReferenceInitFailed,
+ /// \brief Implicit conversion failed.
+ FK_ConversionFailed
+ };
+
+private:
+ /// \brief The reason why initialization failued.
+ FailureKind Failure;
+
+ /// \brief The failed result of overload resolution.
+ OverloadingResult FailedOverloadResult;
+
+ /// \brief The candidate set created when initialization failed.
+ OverloadCandidateSet FailedCandidateSet;
+
+public:
+ /// \brief Try to perform initialization of the given entity, creating a
+ /// record of the steps required to perform the initialization.
+ ///
+ /// The generated initialization sequence will either contain enough
+ /// information to diagnose
+ ///
+ /// \param S the semantic analysis object.
+ ///
+ /// \param Entity the entity being initialized.
+ ///
+ /// \param Kind the kind of initialization being performed.
+ ///
+ /// \param Args the argument(s) provided for initialization.
+ ///
+ /// \param NumArgs the number of arguments provided for initialization.
+ InitializationSequence(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr **Args,
+ unsigned NumArgs);
+
+ ~InitializationSequence();
+
+ /// \brief Perform the actual initialization of the given entity based on
+ /// the computed initialization sequence.
+ ///
+ /// \param S the semantic analysis object.
+ ///
+ /// \param Entity the entity being initialized.
+ ///
+ /// \param Kind the kind of initialization being performed.
+ ///
+ /// \param Args the argument(s) provided for initialization, ownership of
+ /// which is transfered into the routine.
+ ///
+ /// \returns an expression that performs the actual object initialization, if
+ /// the initialization is well-formed. Otherwise, emits diagnostics
+ /// and returns an invalid expression.
+ Action::OwningExprResult Perform(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Action::MultiExprArg Args);
+
+ /// \brief Diagnose an potentially-invalid initialization sequence.
+ ///
+ /// \returns true if the initialization sequence was ill-formed,
+ /// false otherwise.
+ bool Diagnose(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr **Args, unsigned NumArgs);
+
+ /// \brief Determine the kind of initialization sequence computed.
+ enum SequenceKind getKind() const { return SequenceKind; }
+
+ /// \brief Set the kind of sequence computed.
+ void setSequenceKind(enum SequenceKind SK) { SequenceKind = SK; }
+
+ /// \brief Determine whether the initialization sequence is valid.
+ operator bool() const { return SequenceKind != FailedSequence; }
+
+ typedef llvm::SmallVector<Step, 4>::const_iterator step_iterator;
+ step_iterator step_begin() const { return Steps.begin(); }
+ step_iterator step_end() const { return Steps.end(); }
+
+ /// \brief Add a new step in the initialization that resolves the address
+ /// of an overloaded function to a specific function declaration.
+ ///
+ /// \param Function the function to which the overloaded function reference
+ /// resolves.
+ void AddAddressOverloadResolutionStep(FunctionDecl *Function);
+
+ /// \brief Add a new step in the initialization that performs a derived-to-
+ /// base cast.
+ ///
+ /// \param BaseType the base type to which we will be casting.
+ ///
+ /// \param IsLValue true if the result of this cast will be treated as
+ /// an lvalue.
+ void AddDerivedToBaseCastStep(QualType BaseType, bool IsLValue);
+
+ /// \brief Add a new step binding a reference to an object.
+ ///
+ /// \param BindingTemporary true if we are binding a reference to a temporary
+ /// object (thereby extending its lifetime); false if we are binding to an
+ /// lvalue or an lvalue treated as an rvalue.
+ void AddReferenceBindingStep(QualType T, bool BindingTemporary);
+
+ /// \brief Add a new step invoking a conversion function, which is either
+ /// a constructor or a conversion function.
+ void AddUserConversionStep(FunctionDecl *Function);
+
+ /// \brief Add a new step that performs a qualification conversion to the
+ /// given type.
+ void AddQualificationConversionStep(QualType Ty, bool IsLValue);
+
+ /// \brief Add a new step that applies an implicit conversion sequence.
+ void AddConversionSequenceStep(const ImplicitConversionSequence &ICS,
+ QualType T);
+
+ /// \brief Note that this initialization sequence failed.
+ void SetFailed(FailureKind Failure) {
+ SequenceKind = FailedSequence;
+ this->Failure = Failure;
+ }
+
+ /// \brief Note that this initialization sequence failed due to failed
+ /// overload resolution.
+ void SetOverloadFailure(FailureKind Failure, OverloadingResult Result);
+
+ /// \brief Retrieve a reference to the candidate set when overload
+ /// resolution fails.
+ OverloadCandidateSet &getFailedCandidateSet() {
+ return FailedCandidateSet;
+ }
+
+ /// \brief Determine why initialization failed.
+ FailureKind getFailureKind() const {
+ assert(getKind() == FailedSequence && "Not an initialization failure!");
+ return Failure;
+ }
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_INIT_H
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 4443de05380..9ca8d767835 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1399,13 +1399,13 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType) {
/// for overload resolution.
/// \param UserCast true if looking for user defined conversion for a static
/// cast.
-Sema::OverloadingResult Sema::IsUserDefinedConversion(
- Expr *From, QualType ToType,
- UserDefinedConversionSequence& User,
- OverloadCandidateSet& CandidateSet,
- bool AllowConversionFunctions,
- bool AllowExplicit, bool ForceRValue,
- bool UserCast) {
+OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
+ UserDefinedConversionSequence& User,
+ OverloadCandidateSet& CandidateSet,
+ bool AllowConversionFunctions,
+ bool AllowExplicit,
+ bool ForceRValue,
+ bool UserCast) {
if (const RecordType *ToRecordType = ToType->getAs<RecordType>()) {
if (RequireCompleteType(From->getLocStart(), ToType, PDiag())) {
// We're not going to find any constructors.
@@ -4167,10 +4167,9 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1,
/// function, Best points to the candidate function found.
///
/// \returns The result of overload resolution.
-Sema::OverloadingResult
-Sema::BestViableFunction(OverloadCandidateSet& CandidateSet,
- SourceLocation Loc,
- OverloadCandidateSet::iterator& Best) {
+OverloadingResult Sema::BestViableFunction(OverloadCandidateSet& CandidateSet,
+ SourceLocation Loc,
+ OverloadCandidateSet::iterator& Best) {
// Find the best viable function.
Best = CandidateSet.end();
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
@@ -5769,4 +5768,9 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
return E->Retain();
}
+Sema::OwningExprResult Sema::FixOverloadedFunctionReference(OwningExprResult E,
+ FunctionDecl *Fn) {
+ return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Fn));
+}
+
} // end namespace clang
diff --git a/clang/lib/Sema/SemaOverload.h b/clang/lib/Sema/SemaOverload.h
index 5eef3cebe41..3613d608834 100644
--- a/clang/lib/Sema/SemaOverload.h
+++ b/clang/lib/Sema/SemaOverload.h
@@ -15,12 +15,26 @@
#ifndef LLVM_CLANG_SEMA_OVERLOAD_H
#define LLVM_CLANG_SEMA_OVERLOAD_H
+#include "clang/AST/Decl.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
namespace clang {
+ class ASTContext;
class CXXConstructorDecl;
+ class CXXConversionDecl;
class FunctionDecl;
+ /// OverloadingResult - Capture the result of performing overload
+ /// resolution.
+ enum OverloadingResult {
+ OR_Success, ///< Overload resolution succeeded.
+ OR_No_Viable_Function, ///< No viable function found.
+ OR_Ambiguous, ///< Ambiguous candidates found.
+ OR_Deleted ///< Overload resoltuion refers to a deleted function.
+ };
+
/// ImplicitConversionKind - The kind of implicit conversion used to
/// convert an argument to a parameter's type. The enumerator values
/// match with Table 9 of (C++ 13.3.3.1.1) and are listed such that
@@ -271,6 +285,7 @@ namespace clang {
/// OverloadCandidateSet - A set of overload candidates, used in C++
/// overload resolution (C++ 13.3).
class OverloadCandidateSet : public llvm::SmallVector<OverloadCandidate, 16> {
+ typedef llvm::SmallVector<OverloadCandidate, 16> inherited;
llvm::SmallPtrSet<Decl *, 16> Functions;
public:
@@ -279,6 +294,12 @@ namespace clang {
bool isNewCandidate(Decl *F) {
return Functions.insert(F->getCanonicalDecl());
}
+
+ /// \brief Clear out all of the candidates.
+ void clear() {
+ inherited::clear();
+ Functions.clear();
+ }
};
} // end namespace clang
diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp
new file mode 100644
index 00000000000..66fa2d13984
--- /dev/null
+++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp
@@ -0,0 +1,14 @@
+// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s
+int g(int);
+void f() {
+ int i;
+ int& r = i;
+ r = 1;
+ int* p = &r;
+ int &rr=r;
+ int (&rg)(int) = g;
+ rg(i);
+ int a[3];
+ int (&ra)[3] = a;
+ ra[1] = i;
+}
diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp
new file mode 100644
index 00000000000..54840f52663
--- /dev/null
+++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp
@@ -0,0 +1,3 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+int& r1; // expected-error{{declaration of reference variable 'r1' requires an initializer}}
+extern int& r2;
diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp
new file mode 100644
index 00000000000..5d34345c49f
--- /dev/null
+++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp
@@ -0,0 +1,53 @@
+// RUN: clang-cc -ast-dump %s 2>&1 | FileCheck %s
+
+// CHECK: example0
+void example0() {
+ double d = 2.0;
+ // CHECK: double &rd =
+ // CHECK-NEXT: DeclRefExpr
+ double &rd = d;
+ // CHECK: double const &rcd =
+ // CHECK-NEXT: ImplicitCastExpr{{.*}}'double const' <NoOp>
+ const double &rcd = d;
+}
+
+struct A { };
+struct B : A { } b;
+
+// CHECK: example1
+void example1() {
+ // CHECK: struct A &ra =
+ // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase> lvalue
+ A &ra = b;
+ // CHECK: struct A const &rca =
+ // CHECK: ImplicitCastExpr{{.*}}'struct A const' <NoOp>
+ // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase>
+ const A& rca = b;
+}
+
+extern B f();
+
+struct X {
+ operator B();
+} x;
+
+// CHECK: example2
+void example2() {
+ // CHECK: struct A const &rca =
+ // CHECK: ImplicitCastExpr{{.*}}'struct A const' <NoOp>
+ // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase>
+ // CHECK: CallExpr{{.*}}struct B
+ const A &rca = f();
+ // CHECK: struct A const &r =
+ // CHECK: ImplicitCastExpr{{.*}}'struct A const' <NoOp>
+ // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase>
+ // CHECK: CXXMemberCallExpr{{.*}}'struct B'
+ const A& r = x;
+}
+
+// CHECK: example3
+void example3() {
+ // CHECK: double const &rcd2 =
+ // CHECK: ImplicitCastExpr{{.*}}<IntegralToFloating>
+ const double& rcd2 = 2;
+}
diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp
new file mode 100644
index 00000000000..5fa1fff8c86
--- /dev/null
+++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp
@@ -0,0 +1,129 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct Base { }; // expected-note{{candidate function}}
+struct Derived : Base { }; // expected-note{{candidate function}}
+struct Unrelated { };
+struct Derived2 : Base { };
+struct Diamond : Derived, Derived2 { };
+
+struct ConvertibleToBaseRef {
+ operator Base&() const;
+};
+
+struct ConvertibleToDerivedRef {
+ operator Derived&() const;
+};
+
+struct ConvertibleToBothDerivedRef {
+ operator Derived&(); // expected-note{{candidate function}}
+ operator Derived2&(); // expected-note{{candidate function}}
+};
+
+struct ConvertibleToIntRef {
+ operator int&();
+};
+
+struct ConvertibleToBase {
+ operator Base() const;
+};
+
+struct ConvertibleToDerived {
+ operator Derived() const;
+};
+
+struct ConvertibleToBothDerived {
+ operator Derived(); // expected-note{{candidate function}}
+ operator Derived2(); // expected-note{{candidate function}}
+};
+
+struct ConvertibleToInt {
+ operator int();
+};
+
+template<typename T> T create();
+
+// First bullet: lvalue references binding to lvalues (the simple cases).
+void bind_lvalue_to_lvalue(Base b, Derived d,
+ const Base bc, const Derived dc,
+ Diamond diamond,
+ int i) {
+ // Reference-compatible
+ Base &br1 = b;
+ Base &br2 = d;
+ Derived &dr1 = d;
+ Derived &dr2 = b; // expected-error{{non-const lvalue reference to type 'struct Derived' cannot bind to a value of unrelated type 'struct Base'}}
+ Base &br3 = bc; // expected-error{{drops qualifiers}}
+ Base &br4 = dc; // expected-error{{drops qualifiers}}
+ Base &br5 = diamond; // expected-error{{ambiguous conversion from derived class 'struct Diamond' to base class 'struct Base'}}
+ int &ir = i;
+ long &lr = i; // expected-error{{non-const lvalue reference to type 'long' cannot bind to a value of unrelated type 'int'}}
+}
+
+void bind_lvalue_quals(volatile Base b, volatile Derived d,
+ volatile const Base bvc, volatile const Derived dvc,
+ volatile const int ivc) {
+ volatile Base &bvr1 = b;
+ volatile Base &bvr2 = d;
+ volatile Base &bvr3 = bvc; // expected-error{{binding of reference to type 'struct Base volatile' to a value of type 'struct Base const volatile' drops qualifiers}}
+ volatile Base &bvr4 = dvc; // expected-error{{binding of reference to type 'struct Base volatile' to a value of type 'struct Derived const volatile' drops qualifiers}}
+
+ volatile int &ir = ivc; // expected-error{{binding of reference to type 'int volatile' to a value of type 'int const volatile' drops qualifiers}}
+}
+
+void bind_lvalue_to_rvalue() {
+ Base &br1 = Base(); // expected-error{{non-const lvalue reference to type 'struct Base' cannot bind to a temporary of type 'struct Base'}}
+ Base &br2 = Derived(); // expected-error{{non-const lvalue reference to type 'struct Base' cannot bind to a temporary of type 'struct Derived'}}
+
+ int &ir = 17; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
+}
+
+void bind_lvalue_to_unrelated(Unrelated ur) {
+ Base &br1 = ur; // expected-error{{non-const lvalue reference to type 'struct Base' cannot bind to a value of unrelated type 'struct Unrelated'}}
+}
+
+void bind_lvalue_to_conv_lvalue() {
+ // Not reference-related, but convertible
+ Base &nbr1 = ConvertibleToBaseRef();
+ Base &nbr2 = ConvertibleToDerivedRef();
+ Derived &ndr1 = ConvertibleToDerivedRef();
+ int &ir = ConvertibleToIntRef();
+}
+
+void bind_lvalue_to_conv_lvalue_ambig(ConvertibleToBothDerivedRef both) {
+ Derived &dr1 = both;
+ Base &br1 = both; // expected-error{{error: conversion from 'struct ConvertibleToBothDerivedRef' to 'struct Base' is ambiguous}}
+}
+
+struct IntBitfield {
+ int i : 17; // expected-note{{bit-field is declared here}}
+};
+
+void test_bitfield(IntBitfield ib) {
+ int & ir1 = (ib.i); // expected-error{{non-const reference cannot bind to bit-field 'i'}}
+}
+
+// Second bullet: const lvalue reference binding to an rvalue with
+// similar type (both of which are class types).
+void bind_const_lvalue_to_rvalue() {
+ const Base &br1 = create<Base>();
+ const Base &br2 = create<Derived>();
+ const Derived &dr1 = create<Base>(); // expected-error{{no viable conversion}}
+
+ const Base &br3 = create<const Base>();
+ const Base &br4 = create<const Derived>();
+
+ const Base &br5 = create<const volatile Base>(); // expected-error{{binding of reference to type 'struct Base const' to a value of type 'struct Base const volatile' drops qualifiers}}
+ const Base &br6 = create<const volatile Derived>(); // expected-error{{binding of reference to type 'struct Base const' to a value of type 'struct Derived const volatile' drops qualifiers}}
+
+ const int &ir = create<int>();
+}
+
+// Second bullet: const lvalue reference binds to the result of a conversion.
+void bind_const_lvalue_to_class_conv_temporary() {
+ const Base &br1 = ConvertibleToBase();
+ const Base &br2 = ConvertibleToDerived();
+}
+void bind_lvalue_to_conv_rvalue_ambig(ConvertibleToBothDerived both) {
+ const Derived &dr1 = both;
+ const Base &br1 = both; // expected-error{{error: conversion from 'struct ConvertibleToBothDerived' to 'struct Base const' is ambiguous}}
+}
diff --git a/clang/test/CodeGenCXX/references.cpp b/clang/test/CodeGenCXX/references.cpp
index eaaf346d7cc..74dc0ea6d7b 100644
--- a/clang/test/CodeGenCXX/references.cpp
+++ b/clang/test/CodeGenCXX/references.cpp
@@ -1,5 +1,4 @@
// RUN: clang-cc -verify -emit-llvm -o - %s | FileCheck %s
-
void t1() {
extern int& a;
int b = a;
@@ -19,7 +18,6 @@ void t3() {
// Test reference binding.
struct C { int a; };
-
void f(const bool&);
void f(const int&);
void f(const _Complex int&);
diff --git a/clang/test/SemaCXX/convert-to-bool.cpp b/clang/test/SemaCXX/convert-to-bool.cpp
index 937b2729d1c..277bfc6c688 100644
--- a/clang/test/SemaCXX/convert-to-bool.cpp
+++ b/clang/test/SemaCXX/convert-to-bool.cpp
@@ -49,7 +49,7 @@ void test_explicit_bool(ExplicitConvToBool ecb) {
}
void test_explicit_conv_to_ref(ExplicitConvToRef ecr) {
- int& i1 = ecr; // expected-error{{non-const lvalue reference to type 'int' cannot be initialized with a value of type 'struct ExplicitConvToRef'}}
+ int& i1 = ecr; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'struct ExplicitConvToRef'}}
int& i2(ecr); // okay
}
@@ -57,11 +57,11 @@ struct A { };
struct B { };
struct C {
explicit operator A&(); // expected-warning{{explicit conversion functions are a C++0x extension}}
- operator B&();
+ operator B&(); // expected-note{{candidate}}
};
void test_copy_init_conversions(C c) {
- A &a = c; // expected-error{{non-const lvalue reference to type 'struct A' cannot be initialized with a value of type 'struct C'}}
+ A &a = c; // expected-error{{no viable conversion from 'struct C' to 'struct A'}}
B &b = b; // okay
}
diff --git a/clang/test/SemaCXX/decl-init-ref.cpp b/clang/test/SemaCXX/decl-init-ref.cpp
index d7db647cd11..20eb91a608c 100644
--- a/clang/test/SemaCXX/decl-init-ref.cpp
+++ b/clang/test/SemaCXX/decl-init-ref.cpp
@@ -1,6 +1,6 @@
// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s
-struct A {};
+struct A {}; // expected-note {{candidate function}}
struct BASE {
operator A(); // expected-note {{candidate function}}
@@ -21,6 +21,6 @@ extern B f();
const int& ri = (void)0; // expected-error {{invalid initialization of reference of type 'int const &' from expression of type 'void'}}
int main() {
- const A& rca = f(); // expected-error {{rvalue reference cannot bind to lvalue due to multiple conversion functions}}
- A& ra = f(); // expected-error {{non-const lvalue reference to type 'struct A' cannot be initialized with a temporary of type 'class B'}}
+ const A& rca = f(); // expected-error {{conversion from 'class B' to 'struct A const' is ambiguous}}
+ A& ra = f(); // expected-error {{non-const lvalue reference to type 'struct A' cannot bind to a temporary of type 'class B'}}
}
diff --git a/clang/test/SemaCXX/overloaded-operator.cpp b/clang/test/SemaCXX/overloaded-operator.cpp
index 16d37040f14..672b8b4fc26 100644
--- a/clang/test/SemaCXX/overloaded-operator.cpp
+++ b/clang/test/SemaCXX/overloaded-operator.cpp
@@ -67,7 +67,7 @@ void enum_test(Enum1 enum1, Enum2 enum2, E1 e1, E2 e2) {
float &f1 = (e1 == e2);
float &f2 = (enum1 == e2);
float &f3 = (e1 == enum2);
- float &f4 = (enum1 == enum2); // expected-error{{non-const lvalue reference to type 'float' cannot be initialized with a temporary of type 'bool'}}
+ float &f4 = (enum1 == enum2); // expected-error{{non-const lvalue reference to type 'float' cannot bind to a temporary of type 'bool'}}
}
// PR5244 - Argument-dependent lookup would include the two operators below,
diff --git a/clang/test/SemaCXX/ref-init-ambiguous.cpp b/clang/test/SemaCXX/ref-init-ambiguous.cpp
index dda1ead7b62..60620993b43 100644
--- a/clang/test/SemaCXX/ref-init-ambiguous.cpp
+++ b/clang/test/SemaCXX/ref-init-ambiguous.cpp
@@ -3,18 +3,19 @@
enum E2 { };
struct A {
- operator E2&(); // expected-note 3 {{candidate function}}
+ operator E2&(); // expected-note 2 {{candidate function}}
};
struct B {
- operator E2&(); // expected-note 3 {{candidate function}}
+ operator E2&(); // expected-note 2 {{candidate function}}
};
struct C : B, A {
};
void test(C c) {
- const E2 &e2 = c; // expected-error {{reference initialization of type 'enum E2 const &' with initializer of type 'struct C' is ambiguous}}
+ // FIXME: state that there was an ambiguity in the conversion!
+ const E2 &e2 = c; // expected-error {{reference to type 'enum E2 const' could not bind to an lvalue of type 'struct C'}}
}
void foo(const E2 &);
diff --git a/clang/test/SemaCXX/references.cpp b/clang/test/SemaCXX/references.cpp
index e03abf4300a..45d3923ff0a 100644
--- a/clang/test/SemaCXX/references.cpp
+++ b/clang/test/SemaCXX/references.cpp
@@ -44,17 +44,17 @@ B fB();
// C++ [dcl.init.ref]p5b2
void test4() {
- double& rd2 = 2.0; // expected-error{{non-const lvalue reference to type 'double' cannot be initialized with a temporary of type 'double'}}
+ double& rd2 = 2.0; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a temporary of type 'double'}}
int i = 2;
- double& rd3 = i; // expected-error{{non-const lvalue reference to type 'double' cannot be initialized with a value of type 'int'}}
+ double& rd3 = i; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a value of unrelated type 'int'}}
const A& rca = fB();
}
void test5() {
- const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0
+ // const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0
const volatile int cvi = 1;
- const int& r = cvi; // expected-error{{initialization of reference to type 'int const' with a value of type 'int const volatile' drops qualifiers}}
+ const int& r = cvi; // expected-error{{binding of reference to type 'int const' to a value of type 'int const volatile' drops qualifiers}}
}
// C++ [dcl.init.ref]p3
diff --git a/clang/test/SemaCXX/rval-references.cpp b/clang/test/SemaCXX/rval-references.cpp
index 5132c2a69be..7a71607707c 100644
--- a/clang/test/SemaCXX/rval-references.cpp
+++ b/clang/test/SemaCXX/rval-references.cpp
@@ -44,7 +44,7 @@ void f() {
conv_to_not_int_rvalue cnir;
not_int &&ni4 = cnir; // expected-error {{rvalue reference cannot bind to lvalue}}
- not_int &ni5 = cnir; // expected-error{{non-const lvalue reference to type 'struct not_int' cannot be initialized with a value of type 'struct conv_to_not_int_rvalue'}}
+ not_int &ni5 = cnir; // expected-error{{non-const lvalue reference to type 'struct not_int' cannot bind to a value of unrelated type 'struct conv_to_not_int_rvalue'}}
not_int &&ni6 = conv_to_not_int_rvalue();
diff --git a/clang/test/SemaTemplate/instantiate-expr-4.cpp b/clang/test/SemaTemplate/instantiate-expr-4.cpp
index cd74a21d6db..150faec3f2a 100644
--- a/clang/test/SemaTemplate/instantiate-expr-4.cpp
+++ b/clang/test/SemaTemplate/instantiate-expr-4.cpp
@@ -185,7 +185,7 @@ template struct InitList2<APair, int*, double*>; // expected-note{{instantiation
template<typename T, typename Result>
struct DotMemRef0 {
void f(T t) {
- Result result = t.m; // expected-error{{cannot be initialized}}
+ Result result = t.m; // expected-error{{non-const lvalue reference to type}}
}
};
@@ -207,7 +207,7 @@ template struct DotMemRef0<MemInt, float&>; // expected-note{{instantiation}}
template<typename T, typename Result>
struct ArrowMemRef0 {
void f(T t) {
- Result result = t->m; // expected-error 2{{cannot be initialized}}
+ Result result = t->m; // expected-error 2{{non-const lvalue reference}}
}
};
@@ -269,7 +269,7 @@ template struct ThisMemberFuncCall0<int&>;
template<typename T>
struct NonDepMemberCall0 {
void foo(HasMemFunc0<int&> x) {
- T result = x.f(); // expected-error{{initialized}}
+ T result = x.f(); // expected-error{{non-const lvalue reference}}
}
};
OpenPOWER on IntegriCloud