[cfe-commits] r68902 - in /cfe/trunk: include/clang/Parse/Action.h lib/Parse/ParseDeclCXX.cpp lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaStmt.cpp test/SemaCXX/deleted-function.cpp test/SemaCXX/rval-references.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Sun Apr 12 10:16:30 PDT 2009
Author: cornedbee
Date: Sun Apr 12 12:16:29 2009
New Revision: 68902
URL: http://llvm.org/viewvc/llvm-project?rev=68902&view=rev
Log:
Parse deleted member functions. Parsing member declarations goes through a different code path that I forgot previously.
Implement the rvalue reference overload dance for returning local objects. Returning a local object first tries to find a move constructor now.
The error message when no move constructor is defined (or is not applicable) and the copy constructor is deleted is quite ugly, though.
Modified:
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaStmt.cpp
cfe/trunk/test/SemaCXX/deleted-function.cpp
cfe/trunk/test/SemaCXX/rval-references.cpp
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=68902&r1=68901&r2=68902&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Sun Apr 12 12:16:29 2009
@@ -1038,11 +1038,13 @@
/// declarator is parsed. 'AS' is the access specifier, 'BitfieldWidth'
/// specifies the bitfield width if there is one and 'Init' specifies the
/// initializer if any. 'LastInGroup' is non-null for cases where one declspec
- /// has multiple declarators on it.
+ /// has multiple declarators on it. 'Deleted' is true if there's a =delete
+ /// specifier on the function.
virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
Declarator &D,
ExprTy *BitfieldWidth,
- ExprTy *Init) {
+ ExprTy *Init,
+ bool Deleted = false) {
return DeclPtrTy();
}
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=68902&r1=68901&r2=68902&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sun Apr 12 12:16:29 2009
@@ -668,7 +668,7 @@
/// declarator constant-initializer[opt]
/// identifier[opt] ':' constant-expression
///
-/// pure-specifier: [TODO]
+/// pure-specifier:
/// '= 0'
///
/// constant-initializer:
@@ -767,6 +767,7 @@
llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
OwningExprResult BitfieldSize(Actions);
OwningExprResult Init(Actions);
+ bool Deleted = false;
while (1) {
@@ -787,12 +788,21 @@
//
// constant-initializer:
// '=' constant-expression
+ //
+ // defaulted/deleted function-definition:
+ // '=' 'default' [TODO]
+ // '=' 'delete'
if (Tok.is(tok::equal)) {
ConsumeToken();
- Init = ParseInitializer();
- if (Init.isInvalid())
- SkipUntil(tok::comma, true, true);
+ if (getLang().CPlusPlus0x && Tok.is(tok::kw_delete)) {
+ ConsumeToken();
+ Deleted = true;
+ } else {
+ Init = ParseInitializer();
+ if (Init.isInvalid())
+ SkipUntil(tok::comma, true, true);
+ }
}
// If attributes exist after the declarator, parse them.
@@ -808,7 +818,8 @@
DeclPtrTy ThisDecl = Actions.ActOnCXXMemberDeclarator(CurScope, AS,
DeclaratorInfo,
BitfieldSize.release(),
- Init.release());
+ Init.release(),
+ Deleted);
if (ThisDecl)
DeclsInGroup.push_back(ThisDecl);
@@ -858,6 +869,7 @@
DeclaratorInfo.clear();
BitfieldSize = 0;
Init = 0;
+ Deleted = false;
// Attributes are only allowed on the second declarator.
if (Tok.is(tok::kw___attribute)) {
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=68902&r1=68901&r2=68902&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sun Apr 12 12:16:29 2009
@@ -504,7 +504,8 @@
ImplicitConversionSequence
TryImplicitConversion(Expr* From, QualType ToType,
bool SuppressUserConversions = false,
- bool AllowExplicit = false);
+ bool AllowExplicit = false,
+ bool ForceRValue = false);
bool IsStandardConversion(Expr *From, QualType ToType,
StandardConversionSequence& SCS);
bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType);
@@ -522,7 +523,7 @@
bool IsUserDefinedConversion(Expr *From, QualType ToType,
UserDefinedConversionSequence& User,
bool AllowConversionFunctions,
- bool AllowExplicit);
+ bool AllowExplicit, bool ForceRValue);
ImplicitConversionSequence::CompareKind
CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1,
@@ -542,9 +543,10 @@
ImplicitConversionSequence
TryCopyInitialization(Expr* From, QualType ToType,
- bool SuppressUserConversions = false);
+ bool SuppressUserConversions = false,
+ bool ForceRValue = false);
bool PerformCopyInitialization(Expr *&From, QualType ToType,
- const char *Flavor);
+ const char *Flavor, bool Elidable = false);
ImplicitConversionSequence
TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method);
@@ -569,7 +571,8 @@
void AddOverloadCandidate(FunctionDecl *Function,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
- bool SuppressUserConversions = false);
+ bool SuppressUserConversions = false,
+ bool ForceRValue = false);
void AddFunctionCandidates(const FunctionSet &Functions,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
@@ -577,7 +580,8 @@
void AddMethodCandidate(CXXMethodDecl *Method,
Expr *Object, Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
- bool SuppressUserConversions = false);
+ bool SuppressUserConversions = false,
+ bool ForceRValue = false);
void AddConversionCandidate(CXXConversionDecl *Conversion,
Expr *From, QualType ToType,
OverloadCandidateSet& CandidateSet);
@@ -1590,11 +1594,12 @@
//
virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS);
-
+
virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
Declarator &D,
ExprTy *BitfieldWidth,
- ExprTy *Init);
+ ExprTy *Init,
+ bool Deleted = false);
virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorD,
Scope *S,
@@ -2319,7 +2324,9 @@
bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
bool PerformImplicitConversion(Expr *&From, QualType ToType,
- const char *Flavor, bool AllowExplicit = false);
+ const char *Flavor,
+ bool AllowExplicit = false,
+ bool Elidable = false);
bool PerformImplicitConversion(Expr *&From, QualType ToType,
const ImplicitConversionSequence& ICS,
const char *Flavor);
@@ -2415,7 +2422,8 @@
bool CheckReferenceInit(Expr *&simpleInit_or_initList, QualType &declType,
ImplicitConversionSequence *ICS = 0,
bool SuppressUserConversions = false,
- bool AllowExplicit = false);
+ bool AllowExplicit = false,
+ bool ForceRValue = false);
/// CheckCastTypes - Check type constraints for casting between types.
bool CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *&CastExpr);
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=68902&r1=68901&r2=68902&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Apr 12 12:16:29 2009
@@ -473,7 +473,7 @@
/// declarators on it.
Sema::DeclPtrTy
Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
- ExprTy *BW, ExprTy *InitExpr) {
+ ExprTy *BW, ExprTy *InitExpr, bool Deleted) {
const DeclSpec &DS = D.getDeclSpec();
DeclarationName Name = GetNameForDeclarator(D);
Expr *BitWidth = static_cast<Expr*>(BW);
@@ -591,6 +591,8 @@
if (Init)
AddInitializerToDecl(DeclPtrTy::make(Member), ExprArg(*this, Init), false);
+ if (Deleted) // FIXME: Source location is not very good.
+ SetDeclDeleted(DeclPtrTy::make(Member), D.getSourceRange().getBegin());
if (isInstField) {
FieldCollector->Add(cast<FieldDecl>(Member));
@@ -1981,11 +1983,12 @@
/// suppressed.
/// When @p AllowExplicit, we also permit explicit user-defined
/// conversion functions.
+/// When @p ForceRValue, we unconditionally treat the initializer as an rvalue.
bool
Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
ImplicitConversionSequence *ICS,
bool SuppressUserConversions,
- bool AllowExplicit) {
+ bool AllowExplicit, bool ForceRValue) {
assert(DeclType->isReferenceType() && "Reference init needs a reference");
QualType T1 = DeclType->getAsReferenceType()->getPointeeType();
@@ -2014,7 +2017,8 @@
// Compute some basic properties of the types and the initializer.
bool isRValRef = DeclType->isRValueReferenceType();
bool DerivedToBase = false;
- Expr::isLvalueResult InitLvalue = Init->isLvalue(Context);
+ Expr::isLvalueResult InitLvalue = ForceRValue ? Expr::LV_InvalidExpression :
+ Init->isLvalue(Context);
ReferenceCompareResult RefRelationship
= CompareReferenceRelationship(T1, T2, DerivedToBase);
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=68902&r1=68901&r2=68902&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sun Apr 12 12:16:29 2009
@@ -737,13 +737,23 @@
/// error, false otherwise. The expression From is replaced with the
/// converted expression. Flavor is the kind of conversion we're
/// performing, used in the error message. If @p AllowExplicit,
-/// explicit user-defined conversions are permitted.
-bool
+/// explicit user-defined conversions are permitted. @p Elidable should be true
+/// when called for copies which may be elided (C++ 12.8p15). C++0x overload
+/// resolution works differently in that case.
+bool
Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
- const char *Flavor, bool AllowExplicit)
+ const char *Flavor, bool AllowExplicit,
+ bool Elidable)
{
- ImplicitConversionSequence ICS = TryImplicitConversion(From, ToType, false,
- AllowExplicit);
+ ImplicitConversionSequence ICS;
+ ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
+ if (Elidable && getLangOptions().CPlusPlus0x) {
+ ICS = TryImplicitConversion(From, ToType, /*SuppressUserConversions*/false,
+ AllowExplicit, /*ForceRValue*/true);
+ }
+ if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion) {
+ ICS = TryImplicitConversion(From, ToType, false, AllowExplicit);
+ }
return PerformImplicitConversion(From, ToType, ICS, Flavor);
}
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=68902&r1=68901&r2=68902&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Sun Apr 12 12:16:29 2009
@@ -376,17 +376,20 @@
/// not permitted.
/// If @p AllowExplicit, then explicit user-defined conversions are
/// permitted.
+/// If @p ForceRValue, then overloading is performed as if From was an rvalue,
+/// no matter its actual lvalueness.
ImplicitConversionSequence
Sema::TryImplicitConversion(Expr* From, QualType ToType,
bool SuppressUserConversions,
- bool AllowExplicit)
+ bool AllowExplicit, bool ForceRValue)
{
ImplicitConversionSequence ICS;
if (IsStandardConversion(From, ToType, ICS.Standard))
ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
else if (getLangOptions().CPlusPlus &&
IsUserDefinedConversion(From, ToType, ICS.UserDefined,
- !SuppressUserConversions, AllowExplicit)) {
+ !SuppressUserConversions, AllowExplicit,
+ ForceRValue)) {
ICS.ConversionKind = ImplicitConversionSequence::UserDefinedConversion;
// C++ [over.ics.user]p4:
// A conversion of an expression of class type to the same class
@@ -1313,10 +1316,13 @@
/// \param AllowExplicit true if the conversion should consider C++0x
/// "explicit" conversion functions as well as non-explicit conversion
/// functions (C++0x [class.conv.fct]p2).
+///
+/// \param ForceRValue true if the expression should be treated as an rvalue
+/// for overload resolution.
bool Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
UserDefinedConversionSequence& User,
bool AllowConversionFunctions,
- bool AllowExplicit)
+ bool AllowExplicit, bool ForceRValue)
{
OverloadCandidateSet CandidateSet;
if (const RecordType *ToRecordType = ToType->getAsRecordType()) {
@@ -1340,7 +1346,7 @@
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
if (Constructor->isConvertingConstructor())
AddOverloadCandidate(Constructor, &From, 1, CandidateSet,
- /*SuppressUserConversions=*/true);
+ /*SuppressUserConversions=*/true, ForceRValue);
}
}
}
@@ -1856,24 +1862,29 @@
/// sequence required to pass this argument, which may be a bad
/// conversion sequence (meaning that the argument cannot be passed to
/// a parameter of this type). If @p SuppressUserConversions, then we
-/// do not permit any user-defined conversion sequences.
+/// do not permit any user-defined conversion sequences. If @p ForceRValue,
+/// then we treat @p From as an rvalue, even if it is an lvalue.
ImplicitConversionSequence
Sema::TryCopyInitialization(Expr *From, QualType ToType,
- bool SuppressUserConversions) {
+ bool SuppressUserConversions, bool ForceRValue) {
if (ToType->isReferenceType()) {
ImplicitConversionSequence ICS;
- CheckReferenceInit(From, ToType, &ICS, SuppressUserConversions);
+ CheckReferenceInit(From, ToType, &ICS, SuppressUserConversions,
+ /*AllowExplicit=*/false, ForceRValue);
return ICS;
} else {
- return TryImplicitConversion(From, ToType, SuppressUserConversions);
+ return TryImplicitConversion(From, ToType, SuppressUserConversions,
+ ForceRValue);
}
}
-/// PerformArgumentPassing - Pass the argument Arg into a parameter of
-/// type ToType. Returns true (and emits a diagnostic) if there was
-/// an error, returns false if the initialization succeeded.
+/// PerformCopyInitialization - Copy-initialize an object of type @p ToType with
+/// the expression @p From. Returns true (and emits a diagnostic) if there was
+/// an error, returns false if the initialization succeeded. Elidable should
+/// be true when the copy may be elided (C++ 12.8p15). Overload resolution works
+/// differently in C++0x for this case.
bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType,
- const char* Flavor) {
+ const char* Flavor, bool Elidable) {
if (!getLangOptions().CPlusPlus) {
// In C, argument passing is the same as performing an assignment.
QualType FromType = From->getType();
@@ -1883,13 +1894,14 @@
return DiagnoseAssignmentResult(ConvTy, From->getLocStart(), ToType,
FromType, From, Flavor);
}
-
+
if (ToType->isReferenceType())
return CheckReferenceInit(From, ToType);
- if (!PerformImplicitConversion(From, ToType, Flavor))
+ if (!PerformImplicitConversion(From, ToType, Flavor,
+ /*AllowExplicit=*/false, Elidable))
return false;
-
+
return Diag(From->getSourceRange().getBegin(),
diag::err_typecheck_convert_incompatible)
<< ToType << From->getType() << Flavor << From->getSourceRange();
@@ -1997,11 +2009,15 @@
/// candidate functions, using the given function call arguments. If
/// @p SuppressUserConversions, then don't allow user-defined
/// conversions via constructors or conversion operators.
+/// If @p ForceRValue, treat all arguments as rvalues. This is a slightly
+/// hacky way to implement the overloading rules for elidable copy
+/// initialization in C++0x (C++0x 12.8p15).
void
Sema::AddOverloadCandidate(FunctionDecl *Function,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
- bool SuppressUserConversions)
+ bool SuppressUserConversions,
+ bool ForceRValue)
{
const FunctionProtoType* Proto
= dyn_cast<FunctionProtoType>(Function->getType()->getAsFunctionType());
@@ -2017,7 +2033,7 @@
// function, e.g., X::f(). We use a NULL object as the implied
// object argument (C++ [over.call.func]p3).
AddMethodCandidate(Method, 0, Args, NumArgs, CandidateSet,
- SuppressUserConversions);
+ SuppressUserConversions, ForceRValue);
return;
}
@@ -2064,7 +2080,7 @@
QualType ParamType = Proto->getArgType(ArgIdx);
Candidate.Conversions[ArgIdx]
= TryCopyInitialization(Args[ArgIdx], ParamType,
- SuppressUserConversions);
+ SuppressUserConversions, ForceRValue);
if (Candidate.Conversions[ArgIdx].ConversionKind
== ImplicitConversionSequence::BadConversion) {
Candidate.Viable = false;
@@ -2099,12 +2115,14 @@
/// @c o.f(a1,a2), @c Object will contain @c o and @c Args will contain
/// both @c a1 and @c a2. If @p SuppressUserConversions, then don't
/// allow user-defined conversions via constructors or conversion
-/// operators.
+/// operators. If @p ForceRValue, treat all arguments as rvalues. This is
+/// a slightly hacky way to implement the overloading rules for elidable copy
+/// initialization in C++0x (C++0x 12.8p15).
void
Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
- bool SuppressUserConversions)
+ bool SuppressUserConversions, bool ForceRValue)
{
const FunctionProtoType* Proto
= dyn_cast<FunctionProtoType>(Method->getType()->getAsFunctionType());
@@ -2169,7 +2187,7 @@
QualType ParamType = Proto->getArgType(ArgIdx);
Candidate.Conversions[ArgIdx + 1]
= TryCopyInitialization(Args[ArgIdx], ParamType,
- SuppressUserConversions);
+ SuppressUserConversions, ForceRValue);
if (Candidate.Conversions[ArgIdx + 1].ConversionKind
== ImplicitConversionSequence::BadConversion) {
Candidate.Viable = false;
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=68902&r1=68901&r2=68902&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Sun Apr 12 12:16:29 2009
@@ -754,6 +754,32 @@
return Owned(new (Context) ReturnStmt(ReturnLoc, RetValExp));
}
+/// IsReturnCopyElidable - Whether returning @p RetExpr from a function that
+/// returns a @p RetType fulfills the criteria for copy elision (C++0x 12.8p15).
+static bool IsReturnCopyElidable(ASTContext &Ctx, QualType RetType,
+ Expr *RetExpr) {
+ QualType ExprType = RetExpr->getType();
+ // - in a return statement in a function with ...
+ // ... a class return type ...
+ if (!RetType->isRecordType())
+ return false;
+ // ... the same cv-unqualified type as the function return type ...
+ if (Ctx.getCanonicalType(RetType).getUnqualifiedType() !=
+ Ctx.getCanonicalType(ExprType).getUnqualifiedType())
+ return false;
+ // ... the expression is the name of a non-volatile automatic object ...
+ // We ignore parentheses here.
+ // FIXME: Is this compliant?
+ const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(RetExpr->IgnoreParens());
+ if (!DR)
+ return false;
+ const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+ if (!VD)
+ return false;
+ return VD->hasLocalStorage() && !VD->getType()->isReferenceType()
+ && !VD->getType().isVolatileQualified();
+}
+
Action::OwningStmtResult
Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) {
Expr *RetValExp = static_cast<Expr *>(rex.release());
@@ -800,16 +826,31 @@
if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) {
// we have a non-void function with an expression, continue checking
- QualType RetValType = RetValExp->getType();
// C99 6.8.6.4p3(136): The return statement is not an assignment. The
// overlap restriction of subclause 6.5.16.1 does not apply to the case of
// function return.
+ // C++0x 12.8p15: When certain criteria are met, an implementation is
+ // allowed to omit the copy construction of a class object, [...]
+ // - in a return statement in a function with a class return type, when
+ // the expression is the name of a non-volatile automatic object with
+ // the same cv-unqualified type as the function return type, the copy
+ // operation can be omitted [...]
+ // C++0x 12.8p16: When the criteria for elision of a copy operation are met
+ // and the object to be copied is designated by an lvalue, overload
+ // resolution to select the constructor for the copy is first performed
+ // as if the object were designated by an rvalue.
+ // Note that we only compute Elidable if we're in C++0x, since we don't
+ // care otherwise.
+ bool Elidable = getLangOptions().CPlusPlus0x ?
+ IsReturnCopyElidable(Context, FnRetType, RetValExp) :
+ false;
+
// In C++ the return statement is handled via a copy initialization.
// the C version of which boils down to CheckSingleAssignmentConstraints.
- // FIXME: Leaks RetValExp.
- if (PerformCopyInitialization(RetValExp, FnRetType, "returning"))
+ // FIXME: Leaks RetValExp on error.
+ if (PerformCopyInitialization(RetValExp, FnRetType, "returning", Elidable))
return StmtError();
if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
Modified: cfe/trunk/test/SemaCXX/deleted-function.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/deleted-function.cpp?rev=68902&r1=68901&r2=68902&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/deleted-function.cpp (original)
+++ cfe/trunk/test/SemaCXX/deleted-function.cpp Sun Apr 12 12:16:29 2009
@@ -15,8 +15,20 @@
void ov(int) {} // expected-note {{candidate function}}
void ov(double) = delete; // expected-note {{candidate function has been explicitly deleted}}
+struct WithDel {
+ WithDel() = delete; // expected-note {{candidate function has been explicitly deleted}}
+ void fn() = delete; // expected-note {{function has been explicitly marked deleted here}}
+ operator int() = delete;
+ void operator +(int) = delete;
+};
+
void test() {
fn(); // expected-error {{call to deleted function 'fn'}}
ov(1);
ov(1.0); // expected-error {{call to deleted function 'ov'}}
+
+ WithDel dd; // expected-error {{call to deleted constructor of 'dd'}}
+ WithDel *d = 0;
+ d->fn(); // expected-error {{attempt to use a deleted function}}
+ int i = *d; // expected-error {{incompatible type initializing}}
}
Modified: cfe/trunk/test/SemaCXX/rval-references.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/rval-references.cpp?rev=68902&r1=68901&r2=68902&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/rval-references.cpp (original)
+++ cfe/trunk/test/SemaCXX/rval-references.cpp Sun Apr 12 12:16:29 2009
@@ -52,3 +52,40 @@
} catch(int&&) { // expected-error {{cannot catch exceptions by rvalue reference}}
}
}
+
+int&& should_warn(int i) {
+ // FIXME: The stack address return test doesn't reason about casts.
+ return static_cast<int&&>(i); // xpected-warning {{returning reference to temporary}}
+}
+int&& should_not_warn(int&& i) { // But GCC 4.4 does
+ return static_cast<int&&>(i);
+}
+
+
+// Test the return dance. This also tests IsReturnCopyElidable.
+struct MoveOnly {
+ MoveOnly();
+ MoveOnly(const MoveOnly&) = delete;
+ MoveOnly(MoveOnly&&);
+ MoveOnly(int&&);
+};
+
+MoveOnly returning() {
+ MoveOnly mo;
+ return mo;
+}
+
+MoveOnly gmo;
+MoveOnly returningNonEligible() {
+ int i;
+ static MoveOnly mo;
+ MoveOnly &r = mo;
+ if (0) // Copy from global can't be elided
+ return gmo; // expected-error {{incompatible type returning}}
+ else if (0) // Copy from local static can't be elided
+ return mo; // expected-error {{incompatible type returning}}
+ else if (0) // Copy from reference can't be elided
+ return r; // expected-error {{incompatible type returning}}
+ else // Construction from different type can't be elided
+ return i; // expected-error {{incompatible type returning}}
+}
More information about the cfe-commits
mailing list