Expr *getDefaultArg() { return DefaultArg; }
void setDefaultArg(Expr *defarg) { DefaultArg = defarg; }
+ /// hasUnparsedDefaultArg - Determines whether this parameter has a
+ /// default argument that has not yet been parsed. This will occur
+ /// during the processing of a C++ class whose member functions have
+ /// default arguments, e.g.,
+ /// @code
+ /// class X {
+ /// public:
+ /// void f(int x = 17); // x has an unparsed default argument now
+ /// }; // x has a regular default argument now
+ /// @endcode
+ bool hasUnparsedDefaultArg() const {
+ return DefaultArg == reinterpret_cast<Expr *>(-1);
+ }
+
+ /// setUnparsedDefaultArg - Specify that this parameter has an
+ /// unparsed default argument. The argument will be replaced with a
+ /// real default argument via setDefaultArg when the class
+ /// definition enclosing the function declaration that owns this
+ /// default argument is completed.
+ void setUnparsedDefaultArg() { DefaultArg = reinterpret_cast<Expr *>(-1); }
+
QualType getOriginalType() const;
// Implement isa/cast/dyncast/etc.
// Param is the parameter whose default argument is used by this
// expression.
explicit CXXDefaultArgExpr(ParmVarDecl *param)
- : Expr(CXXDefaultArgExprClass, param->getDefaultArg()->getType()),
+ : Expr(CXXDefaultArgExprClass,
+ param->hasUnparsedDefaultArg()? param->getType().getNonReferenceType()
+ : param->getDefaultArg()->getType()),
Param(param) { }
// Retrieve the parameter that the argument was created from.
// FIXME: %2 is an english string here.
DIAG(err_typecheck_convert_incompatible, ERROR,
"incompatible type %2 %1, expected %0")
+DIAG(err_cannot_initialize_decl_noname, ERROR,
+ "cannot initialize a value of type %0 with an %select{rvalue|lvalue}1 of type %2")
+DIAG(err_cannot_initialize_decl, ERROR,
+ "cannot initialize %0 with an %select{rvalue|lvalue}1 of type %2")
DIAG(warn_incompatible_qualified_id, WARNING,
"incompatible type %2 %1, expected %0")
DIAG(warn_incompatible_qualified_id_operands, WARNING,
ExprTy *defarg) {
}
+ /// ActOnParamUnparsedDefaultArgument - We've seen a default
+ /// argument for a function parameter, but we can't parse it yet
+ /// because we're inside a class definition. Note that this default
+ /// argument will be parsed later.
+ virtual void ActOnParamUnparsedDefaultArgument(DeclTy *param,
+ SourceLocation EqualLoc) { }
+
/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
/// the default argument for the parameter param failed.
virtual void ActOnParamDefaultArgumentError(DeclTy *param) { }
void DumpType(QualType T) {
fprintf(F, "'%s'", T.getAsString().c_str());
- // If the type is directly a typedef, strip off typedefness to give at
- // least one level of concreteness.
- if (TypedefType *TDT = dyn_cast<TypedefType>(T)) {
- QualType Simplified =
- TDT->LookThroughTypedefs().getQualifiedType(T.getCVRQualifiers());
- fprintf(F, ":'%s'", Simplified.getAsString().c_str());
+ if (!T.isNull()) {
+ // If the type is directly a typedef, strip off typedefness to give at
+ // least one level of concreteness.
+ if (TypedefType *TDT = dyn_cast<TypedefType>(T)) {
+ QualType Simplified =
+ TDT->LookThroughTypedefs().getQualifiedType(T.getCVRQualifiers());
+ fprintf(F, ":'%s'", Simplified.getAsString().c_str());
+ }
}
}
void DumpStmt(const Stmt *Node) {
void QualType::getAsStringInternal(std::string &S) const {
if (isNull()) {
- S += "NULL TYPE\n";
+ S += "NULL TYPE";
return;
}
// ActOnParamDefaultArgument will reject the default argument in
// C.
if (Tok.is(tok::equal)) {
+ SourceLocation EqualLoc = Tok.getLocation();
+
// Parse the default argument
if (D.getContext() == Declarator::MemberContext) {
// If we're inside a class definition, cache the tokens
tok::semi, false)) {
delete DefArgToks;
DefArgToks = 0;
- }
+ Actions.ActOnParamDefaultArgumentError(Param);
+ } else
+ Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc);
} else {
// Consume the '='.
- SourceLocation EqualLoc = ConsumeToken();
+ ConsumeToken();
OwningExprResult DefArgResult(ParseAssignmentExpression());
if (DefArgResult.isInvalid()) {
virtual void ActOnParamDefaultArgument(DeclTy *param,
SourceLocation EqualLoc,
ExprTy *defarg);
+ virtual void ActOnParamUnparsedDefaultArgument(DeclTy *param,
+ SourceLocation EqualLoc);
virtual void ActOnParamDefaultArgumentError(DeclTy *param);
void AddInitializerToDecl(DeclTy *dcl, ExprArg init);
void ActOnUninitializedDecl(DeclTy *dcl);
if (!PerformImplicitConversion(Init, DeclType, "initializing"))
return false;
- return Diag(InitLoc, diag::err_typecheck_convert_incompatible)
- << DeclType << InitEntity << "initializing"
- << Init->getSourceRange();
+ if (InitEntity)
+ return Diag(InitLoc, diag::err_cannot_initialize_decl)
+ << InitEntity << (int)(Init->isLvalue(Context) == Expr::LV_Valid)
+ << Init->getType() << Init->getSourceRange();
+ else
+ return Diag(InitLoc, diag::err_cannot_initialize_decl_noname)
+ << DeclType << (int)(Init->isLvalue(Context) == Expr::LV_Valid)
+ << Init->getType() << Init->getSourceRange();
}
// C99 6.7.8p16.
// a declaration of a variable of the parameter type, using the
// copy-initialization semantics (8.5).
Expr *DefaultArgPtr = DefaultArg.get();
- bool DefaultInitFailed = PerformCopyInitialization(DefaultArgPtr, ParamType,
- "in default argument");
+ bool DefaultInitFailed = CheckInitializerTypes(DefaultArgPtr, ParamType,
+ EqualLoc,
+ Param->getDeclName());
if (DefaultArgPtr != DefaultArg.get()) {
DefaultArg.take();
DefaultArg.reset(DefaultArgPtr);
Param->setDefaultArg(DefaultArg.take());
}
+/// ActOnParamUnparsedDefaultArgument - We've seen a default
+/// argument for a function parameter, but we can't parse it yet
+/// because we're inside a class definition. Note that this default
+/// argument will be parsed later.
+void Sema::ActOnParamUnparsedDefaultArgument(DeclTy *param,
+ SourceLocation EqualLoc) {
+ ParmVarDecl *Param = (ParmVarDecl*)param;
+ if (Param)
+ Param->setUnparsedDefaultArg();
+}
+
/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
/// the default argument for the parameter param failed.
void Sema::ActOnParamDefaultArgumentError(DeclTy *param) {
if (chunk.Kind == DeclaratorChunk::Function) {
for (unsigned argIdx = 0; argIdx < chunk.Fun.NumArgs; ++argIdx) {
ParmVarDecl *Param = (ParmVarDecl *)chunk.Fun.ArgInfo[argIdx].Param;
- if (Param->getDefaultArg()) {
- Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
- << Param->getDefaultArg()->getSourceRange();
- Param->setDefaultArg(0);
- } else if (CachedTokens *Toks
- = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens) {
+ if (Param->hasUnparsedDefaultArg()) {
+ CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens;
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
<< SourceRange((*Toks)[1].getLocation(), Toks->back().getLocation());
delete Toks;
chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0;
+ } else if (Param->getDefaultArg()) {
+ Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
+ << Param->getDefaultArg()->getSourceRange();
+ Param->setDefaultArg(0);
}
}
}
for (p = 0; p <= LastMissingDefaultArg; ++p) {
ParmVarDecl *Param = FD->getParamDecl(p);
if (Param->getDefaultArg()) {
- delete Param->getDefaultArg();
+ if (!Param->hasUnparsedDefaultArg())
+ Param->getDefaultArg()->Destroy(Context);
Param->setDefaultArg(0);
}
}
ActOnFields(S, RLoc, TagDecl,
(DeclTy**)FieldCollector->getCurFields(),
FieldCollector->getCurNumFields(), LBrac, RBrac, 0);
+ AddImplicitlyDeclaredMembersToClass(cast<CXXRecordDecl>((Decl*)TagDecl));
}
/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
void Sema::ActOnFinishCXXClassDef(DeclTy *D) {
CXXRecordDecl *Rec = cast<CXXRecordDecl>(static_cast<Decl *>(D));
FieldCollector->FinishClass();
- AddImplicitlyDeclaredMembersToClass(Rec);
PopDeclContext();
// Everything, including inline method definitions, have been parsed.
/// ActOnParamDefaultArgument event for this parameter.
void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclTy *ParamD) {
ParmVarDecl *Param = (ParmVarDecl*)ParamD;
+
+ // If this parameter has an unparsed default argument, clear it out
+ // to make way for the parsed default argument.
+ if (Param->hasUnparsedDefaultArg())
+ Param->setDefaultArg(0);
+
S->AddDecl(Param);
if (Param->getDeclName())
IdResolver.AddDecl(Param);
if (Op != OO_Call) {
for (FunctionDecl::param_iterator Param = FnDecl->param_begin();
Param != FnDecl->param_end(); ++Param) {
- if (Expr *DefArg = (*Param)->getDefaultArg())
+ if ((*Param)->hasUnparsedDefaultArg())
+ return Diag((*Param)->getLocation(),
+ diag::err_operator_overload_default_arg)
+ << FnDecl->getDeclName();
+ else if (Expr *DefArg = (*Param)->getDefaultArg())
return Diag((*Param)->getLocation(),
diag::err_operator_overload_default_arg)
<< FnDecl->getDeclName() << DefArg->getSourceRange();
QualType ProtoArgType = Proto->getArgType(i);
Expr *Arg;
- if (i < NumArgs)
+ if (i < NumArgs) {
Arg = Args[i];
- else
+
+ // Pass the argument.
+ if (PerformCopyInitialization(Arg, ProtoArgType, "passing"))
+ return true;
+ } else
+ // We already type-checked the argument, so we know it works.
Arg = new CXXDefaultArgExpr(FDecl->getParamDecl(i));
QualType ArgType = Arg->getType();
-
- // Pass the argument.
- if (PerformCopyInitialization(Arg, ProtoArgType, "passing"))
- return true;
-
+
Call->setArg(i, Arg);
}
for (;s;) ; // expected-error {{expression must have bool type (or be convertible to bool) ('struct S' invalid)}}
switch (s) {} // expected-error {{statement requires expression of integer type ('struct S' invalid)}}
- while (struct S {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{incompatible type}} expected-error {{expression must have bool type}}
- while (struct {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{incompatible type}} expected-error {{expression must have bool type}}
+ while (struct S {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize 'x' with an rvalue of type 'int'}} expected-error {{expression must have bool type}}
+ while (struct {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize 'x' with an rvalue of type 'int'}} expected-error {{expression must have bool type}}
switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{incompatible type}}
if (int x=0) { // expected-note {{previous definition is here}}
// RUN: clang -fsyntax-only -verify %s
-
typedef int INT;
class Foo {
y(int);
};
extern y b;
+
+struct Length {
+ Length l() const { return *this; }
+};
X x1 = y; // expected-error{{no matching constructor for initialization of 'x1'; candidate is:}}
X x2 = 0;
X x3 = ip;
- X x4 = fp; // expected-error{{incompatible type initializing 'x4', expected 'class X'}}
+ X x4 = fp; // expected-error{{cannot initialize 'x4' with an lvalue of type 'float *'}}
}
explicit Y(int);
};
-void k(Y y = 17); // expected-error{{incompatible type in default argument}}
+void k(Y y = 17); // expected-error{{cannot initialize 'y' with an rvalue of type 'int'}}
+
+void kk(Y = 17); // expected-error{{cannot initialize a value of type 'struct Y' with an rvalue of type 'int'}}
Z z2; // expected-error{{no matching constructor for initialization}}
Z z3(z);
}
+
+ void test_Z(const Z& z) {
+ Z z2(z); // expected-error{{no matching constructor for initialization of 'z2'}}
+ }
};
void test_Z(const Z& z) {
Z z2(z); // expected-error{{no matching constructor for initialization of 'z2'}}
}
+
+struct ZZ {
+ void f(ZZ z = g()); // expected-error{{no matching constructor for initialization}}
+
+ static ZZ g(int = 17);
+
+ ZZ(ZZ&, int = 17); // expected-note{{candidate function}}
+};