[cfe-commits] r90992 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ lib/AST/ lib/Sema/ test/CXX/dcl.decl/dcl.init/dcl.init.ref/ test/CodeGenCXX/ test/SemaCXX/ test/SemaTemplate/
Douglas Gregor
dgregor at apple.com
Wed Dec 9 15:02:17 PST 2009
Author: dgregor
Date: Wed Dec 9 17:02:17 2009
New Revision: 90992
URL: http://llvm.org/viewvc/llvm-project?rev=90992&view=rev
Log:
Reimplement reference initialization (C++ [dcl.init.ref]) using the
new notion of an "initialization sequence", which encapsulates the
computation of the initialization sequence along with diagnostic
information and the capability to turn the computed sequence into an
expression. At present, I've only switched one CheckReferenceInit
callers over to this new mechanism; more will follow.
Aside from (hopefully) being much more true to the standard, the
diagnostics provided by this reference-initialization code are a bit
better than before. Some examples:
p5-var.cpp:54:12: error: non-const lvalue reference to type 'struct
Derived'
cannot bind to a value of unrelated type 'struct Base'
Derived &dr2 = b; // expected-error{{non-const lvalue reference to
...
^ ~
p5-var.cpp:55:9: error: binding of reference to type 'struct Base' to
a value of
type 'struct Base const' drops qualifiers
Base &br3 = bc; // expected-error{{drops qualifiers}}
^ ~~
p5-var.cpp:57:15: error: ambiguous conversion from derived class
'struct Diamond' to base class 'struct Base':
struct Diamond -> struct Derived -> struct Base
struct Diamond -> struct Derived2 -> struct Base
Base &br5 = diamond; // expected-error{{ambiguous conversion from
...
^~~~~~~
p5-var.cpp:59:9: error: non-const lvalue reference to type 'long'
cannot bind to
a value of unrelated type 'int'
long &lr = i; // expected-error{{non-const lvalue reference to type
...
^ ~
p5-var.cpp:74:9: error: non-const lvalue reference to type 'struct
Base' cannot
bind to a temporary of type 'struct Base'
Base &br1 = Base(); // expected-error{{non-const lvalue reference to
...
^ ~~~~~~
p5-var.cpp:102:9: error: non-const reference cannot bind to bit-field
'i'
int & ir1 = (ib.i); // expected-error{{non-const reference cannot
...
^ ~~~~~~
p5-var.cpp:98:7: note: bit-field is declared here
int i : 17; // expected-note{{bit-field is declared here}}
^
Added:
cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp
cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp
cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp
cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaCXXCast.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaInit.h
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaOverload.h
cfe/trunk/test/CodeGenCXX/references.cpp
cfe/trunk/test/SemaCXX/convert-to-bool.cpp
cfe/trunk/test/SemaCXX/decl-init-ref.cpp
cfe/trunk/test/SemaCXX/overloaded-operator.cpp
cfe/trunk/test/SemaCXX/ref-init-ambiguous.cpp
cfe/trunk/test/SemaCXX/references.cpp
cfe/trunk/test/SemaCXX/rval-references.cpp
cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Wed Dec 9 17:02:17 2009
@@ -108,6 +108,7 @@
/// 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.
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed Dec 9 17:02:17 2009
@@ -813,8 +813,9 @@
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).
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Dec 9 17:02:17 2009
@@ -445,6 +445,7 @@
"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_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 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_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">;
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed Dec 9 17:02:17 2009
@@ -434,6 +434,18 @@
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
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Dec 9 17:02:17 2009
@@ -95,7 +95,10 @@
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 @@
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 @@
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 @@
/// 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,
Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Wed Dec 9 17:02:17 2009
@@ -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 @@
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;
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Dec 9 17:02:17 2009
@@ -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 @@
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 @@
SourceRange(Var->getLocation(),
Var->getLocation()),
Var->getDeclName(),
- IK_Default,
+ InitializationKind::CreateDefault(Var->getLocation()),
ConstructorArgs);
// FIXME: Location info for the variable initialization?
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Dec 9 17:02:17 2009
@@ -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 @@
NumArgs),
IdLoc,
SourceRange(IdLoc, RParenLoc),
- Member->getDeclName(), IK_Direct,
+ Member->getDeclName(),
+ InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc),
ConstructorArgs);
if (C) {
@@ -1232,7 +1234,8 @@
(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 @@
SourceRange(VDecl->getLocation(),
RParenLoc),
VDecl->getDeclName(),
- IK_Direct,
+ InitializationKind::CreateDirect(VDecl->getLocation(),
+ LParenLoc,
+ RParenLoc),
ConstructorArgs);
if (!Constructor)
RealDecl->setInvalidDecl();
@@ -3692,7 +3697,7 @@
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 @@
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 @@
// real, update the initializer with the resulting function.
if (!ICS) {
if (DiagnoseUseOfDecl(Fn, DeclLoc))
- return true;
+ return true;
Init = FixOverloadedFunctionReference(Init, Fn);
}
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Dec 9 17:02:17 2009
@@ -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 @@
SourceRange(TypeRange.getBegin(),
RParenLoc),
DeclarationName(),
- IK_Direct,
+ InitializationKind::CreateDirect(TypeRange.getBegin(),
+ LParenLoc,
+ RParenLoc),
ConstructorArgs);
if (!Constructor)
@@ -449,12 +452,17 @@
// 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 @@
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 @@
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 @@
// the viable candidates.
break;
- case Sema::OR_Deleted:
+ case OR_Deleted:
assert(false && "Conditional operator has only built-in overloads");
break;
}
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Dec 9 17:02:17 2009
@@ -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 @@
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 @@
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 @@
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 @@
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;
+}
Modified: cfe/trunk/lib/Sema/SemaInit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.h?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.h (original)
+++ cfe/trunk/lib/Sema/SemaInit.h Wed Dec 9 17:02:17 2009
@@ -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
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Dec 9 17:02:17 2009
@@ -1399,13 +1399,13 @@
/// 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 @@
/// 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 @@
return E->Retain();
}
+Sema::OwningExprResult Sema::FixOverloadedFunctionReference(OwningExprResult E,
+ FunctionDecl *Fn) {
+ return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Fn));
+}
+
} // end namespace clang
Modified: cfe/trunk/lib/Sema/SemaOverload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.h?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.h (original)
+++ cfe/trunk/lib/Sema/SemaOverload.h Wed Dec 9 17:02:17 2009
@@ -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 @@
/// 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 @@
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
Added: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp?rev=90992&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp Wed Dec 9 17:02:17 2009
@@ -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;
+}
Added: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp?rev=90992&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp Wed Dec 9 17:02:17 2009
@@ -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;
Added: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp?rev=90992&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp Wed Dec 9 17:02:17 2009
@@ -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;
+}
Added: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp?rev=90992&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp Wed Dec 9 17:02:17 2009
@@ -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}}
+}
Modified: cfe/trunk/test/CodeGenCXX/references.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/references.cpp?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/references.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/references.cpp Wed Dec 9 17:02:17 2009
@@ -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 @@
// Test reference binding.
struct C { int a; };
-
void f(const bool&);
void f(const int&);
void f(const _Complex int&);
Modified: cfe/trunk/test/SemaCXX/convert-to-bool.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/convert-to-bool.cpp?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/convert-to-bool.cpp (original)
+++ cfe/trunk/test/SemaCXX/convert-to-bool.cpp Wed Dec 9 17:02:17 2009
@@ -49,7 +49,7 @@
}
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 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
}
Modified: cfe/trunk/test/SemaCXX/decl-init-ref.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/decl-init-ref.cpp?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/decl-init-ref.cpp (original)
+++ cfe/trunk/test/SemaCXX/decl-init-ref.cpp Wed Dec 9 17:02:17 2009
@@ -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 @@
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'}}
}
Modified: cfe/trunk/test/SemaCXX/overloaded-operator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-operator.cpp?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overloaded-operator.cpp (original)
+++ cfe/trunk/test/SemaCXX/overloaded-operator.cpp Wed Dec 9 17:02:17 2009
@@ -67,7 +67,7 @@
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,
Modified: cfe/trunk/test/SemaCXX/ref-init-ambiguous.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ref-init-ambiguous.cpp?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/ref-init-ambiguous.cpp (original)
+++ cfe/trunk/test/SemaCXX/ref-init-ambiguous.cpp Wed Dec 9 17:02:17 2009
@@ -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 &);
Modified: cfe/trunk/test/SemaCXX/references.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/references.cpp?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/references.cpp (original)
+++ cfe/trunk/test/SemaCXX/references.cpp Wed Dec 9 17:02:17 2009
@@ -44,17 +44,17 @@
// 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
Modified: cfe/trunk/test/SemaCXX/rval-references.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/rval-references.cpp?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/rval-references.cpp (original)
+++ cfe/trunk/test/SemaCXX/rval-references.cpp Wed Dec 9 17:02:17 2009
@@ -44,7 +44,7 @@
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();
Modified: cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp?rev=90992&r1=90991&r2=90992&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp Wed Dec 9 17:02:17 2009
@@ -185,7 +185,7 @@
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<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<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}}
}
};
More information about the cfe-commits
mailing list