/// expensive string manipulation, so it should be called only when
/// absolutely critical. For simple declarations, @c
/// getIdentifierName() should suffice.
- std::string getName() const;
+ std::string getName() const { return Name.getAsString(); }
static bool classof(const Decl *D) {
return D->getKind() >= NamedFirst && D->getKind() <= NamedLast;
public:
static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, QualType T,
+ DeclarationName N, QualType T,
StorageClass S = None, bool isInline = false,
ScopedDecl *PrevDecl = 0,
SourceLocation TSStartLoc = SourceLocation());
isa<CXXConversionDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&
"Overloaded functions must have the same name");
Functions.push_back(FD);
+
+ // An overloaded function declaration always has the location of
+ // the most-recently-added function declaration.
+ if (FD->getLocation().isValid())
+ this->setLocation(FD->getLocation());
}
function_iterator function_begin() { return Functions.begin(); }
public:
static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, IdentifierInfo *Id,
+ SourceLocation L, DeclarationName N,
QualType T, bool isStatic = false,
bool isInline = false, ScopedDecl *PrevDecl = 0);
/// getNameKind - Determine what kind of name this is.
NameKind getNameKind() const;
+ /// getName - Retrieve the human-readable string for this name.
+ std::string getAsString() const;
+
/// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in
/// this declaration name, or NULL if this declaration name isn't a
/// simple identifier.
"type specifier required for unnamed parameter, defaults to int")
DIAG(err_missing_param, ERROR,
"expected parameter declarator")
+DIAG(err_bad_variable_name, ERROR,
+ "'%0' cannot be the name of a variable or data member")
DIAG(err_declarator_need_ident, ERROR,
"declarator requires an identifier")
/// overloadable operators in C++.
IdentifierInfo *OverloadedOperators[NUM_OVERLOADED_OPERATORS];
- /// ConstructorId - Placeholder identifier for C++ constructors.
- IdentifierInfo *ConstructorId;
-
- /// DestructorId - Placeholder identifier for C++ destructor.
- IdentifierInfo *DestructorId;
-
- /// ConversionFunctionId - Placeholder identifier for a C++
- /// conversion function.
- IdentifierInfo *ConversionFunctionId;
-
public:
/// IdentifierTable ctor - Create the identifier table, populating it with
/// info about the language keywords for the language specified by LangOpts.
return *OverloadedOperators[Op];
}
- /// getConstructorId - Return a placeholder identifier for a C++
- /// constructor.
- IdentifierInfo &getConstructorId();
-
- /// getDestructorId - Return a placeholder identifier for a C++
- /// destructor.
- IdentifierInfo &getDestructorId();
-
- /// getConversionFunctionId - Return a placeholder identifier for a
- /// C++ conversion function.
- IdentifierInfo &getConversionFunctionId();
-
typedef HashTableTy::const_iterator iterator;
typedef HashTableTy::const_iterator const_iterator;
/// isPastIdentifier - Return true if we have parsed beyond the point where
/// the
bool isPastIdentifier() const { return IdentifierLoc.isValid(); }
-
+
+ /// hasName - Whether this declarator has a name, which might be an
+ /// identifier (accessible via getIdentifier()) or some kind of
+ /// special C++ name (constructor, destructor, etc.).
+ bool hasName() const { return getKind() != DK_Abstract; }
+
IdentifierInfo *getIdentifier() const { return Identifier; }
SourceLocation getIdentifierLoc() const { return IdentifierLoc; }
Kind = DK_Abstract;
}
- /// SetConstructor - Set this declarator to be a C++ constructor
+ /// setConstructor - Set this declarator to be a C++ constructor
/// declarator.
- void SetConstructor(Action::TypeTy *Ty, IdentifierInfo *ID,
- SourceLocation Loc) {
- Identifier = ID;
+ void setConstructor(Action::TypeTy *Ty, SourceLocation Loc) {
IdentifierLoc = Loc;
Kind = DK_Constructor;
Type = Ty;
}
- /// SetDestructor - Set this declarator to be a C++ destructor
+ /// setDestructor - Set this declarator to be a C++ destructor
/// declarator.
- void SetDestructor(Action::TypeTy *Ty, IdentifierInfo *ID,
- SourceLocation Loc) {
- Identifier = ID;
+ void setDestructor(Action::TypeTy *Ty, SourceLocation Loc) {
IdentifierLoc = Loc;
Kind = DK_Destructor;
Type = Ty;
}
- // SetConversionFunction - Set this declarator to be a C++
+ // setConversionFunction - Set this declarator to be a C++
// conversion function declarator.
- void SetConversionFunction(Action::TypeTy *Ty, IdentifierInfo *ID,
- SourceLocation Loc) {
- Identifier = ID;
+ void setConversionFunction(Action::TypeTy *Ty, SourceLocation Loc) {
+ Identifier = 0;
IdentifierLoc = Loc;
Kind = DK_Conversion;
Type = Ty;
FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
- IdentifierInfo *Id, QualType T,
+ DeclarationName N, QualType T,
StorageClass S, bool isInline,
ScopedDecl *PrevDecl,
SourceLocation TypeSpecStartLoc) {
void *Mem = C.getAllocator().Allocate<FunctionDecl>();
- return new (Mem) FunctionDecl(Function, DC, L, Id, T, S, isInline, PrevDecl,
+ return new (Mem) FunctionDecl(Function, DC, L, N, T, S, isInline, PrevDecl,
TypeSpecStartLoc);
}
return new (Mem) FileScopeAsmDecl(L, Str);
}
-//===----------------------------------------------------------------------===//
-// NamedDecl Implementation
-//===----------------------------------------------------------------------===//
-
-std::string NamedDecl::getName() const {
- switch (Name.getNameKind()) {
- case DeclarationName::Identifier:
- if (const IdentifierInfo *II = Name.getAsIdentifierInfo())
- return II->getName();
- return "";
-
- case DeclarationName::ObjCZeroArgSelector:
- case DeclarationName::ObjCOneArgSelector:
- case DeclarationName::ObjCMultiArgSelector:
- return Name.getObjCSelector().getName();
-
- case DeclarationName::CXXConstructorName: {
- QualType ClassType = Name.getCXXNameType();
- if (const RecordType *ClassRec = ClassType->getAsRecordType())
- return ClassRec->getDecl()->getName();
- return ClassType.getAsString();
- }
-
- case DeclarationName::CXXDestructorName: {
- std::string Result = "~";
- QualType Type = Name.getCXXNameType();
- if (const RecordType *Rec = Type->getAsRecordType())
- Result += Rec->getDecl()->getName();
- else
- Result += Type.getAsString();
- return Result;
- }
-
- case DeclarationName::CXXConversionFunctionName: {
- std::string Result = "operator ";
- QualType Type = Name.getCXXNameType();
- if (const RecordType *Rec = Type->getAsRecordType())
- Result += Rec->getDecl()->getName();
- else
- Result += Type.getAsString();
- return Result;
- }
- }
-
- assert(false && "Unexpected declaration name kind");
- return "";
-}
-
//===----------------------------------------------------------------------===//
// ScopedDecl Implementation
//===----------------------------------------------------------------------===//
CXXMethodDecl *
CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, IdentifierInfo *Id,
+ SourceLocation L, DeclarationName N,
QualType T, bool isStatic, bool isInline,
ScopedDecl *PrevDecl) {
void *Mem = C.getAllocator().Allocate<CXXMethodDecl>();
- return new (Mem) CXXMethodDecl(CXXMethod, RD, L, Id, T, isStatic, isInline, PrevDecl);
+ return new (Mem) CXXMethodDecl(CXXMethod, RD, L, N, T, isStatic, isInline,
+ PrevDecl);
}
QualType CXXMethodDecl::getThisType(ASTContext &C) const {
//
//===----------------------------------------------------------------------===//
#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/Decl.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Bitcode/Serialize.h"
return Identifier;
}
+std::string DeclarationName::getAsString() const {
+ switch (getNameKind()) {
+ case Identifier:
+ if (const IdentifierInfo *II = getAsIdentifierInfo())
+ return II->getName();
+ return "";
+
+ case ObjCZeroArgSelector:
+ case ObjCOneArgSelector:
+ case ObjCMultiArgSelector:
+ return getObjCSelector().getName();
+
+ case CXXConstructorName: {
+ QualType ClassType = getCXXNameType();
+ if (const RecordType *ClassRec = ClassType->getAsRecordType())
+ return ClassRec->getDecl()->getName();
+ return ClassType.getAsString();
+ }
+
+ case CXXDestructorName: {
+ std::string Result = "~";
+ QualType Type = getCXXNameType();
+ if (const RecordType *Rec = Type->getAsRecordType())
+ Result += Rec->getDecl()->getName();
+ else
+ Result += Type.getAsString();
+ return Result;
+ }
+
+ case CXXConversionFunctionName: {
+ std::string Result = "operator ";
+ QualType Type = getCXXNameType();
+ if (const RecordType *Rec = Type->getAsRecordType())
+ Result += Rec->getDecl()->getName();
+ else
+ Result += Type.getAsString();
+ return Result;
+ }
+ }
+
+ assert(false && "Unexpected declaration name kind");
+ return "";
+}
+
QualType DeclarationName::getCXXNameType() const {
if (CXXSpecialName *CXXName = getAsCXXSpecialName())
return CXXName->Type;
IdentifierTable::IdentifierTable(const LangOptions &LangOpts)
// Start with space for 8K identifiers.
- : HashTable(8192),
- ConstructorId(0), DestructorId(0), ConversionFunctionId(0) {
+ : HashTable(8192) {
// Populate the identifier table with info about keywords for the current
// language.
// This cstor is intended to be used only for serialization.
IdentifierTable::IdentifierTable()
- : HashTable(8192),
- ConstructorId(0), DestructorId(0), ConversionFunctionId(0) { }
-
-/// getConstructorId - Return a placeholder identifier for a C++
-/// constructor.
-IdentifierInfo &IdentifierTable::getConstructorId() {
- if (!ConstructorId)
- ConstructorId = &get("<constructor>");
- return *ConstructorId;
-}
-
-/// getDestructorId - Return a placeholder identifier for a C++
-/// destructor.
-IdentifierInfo &IdentifierTable::getDestructorId() {
- if (!DestructorId)
- DestructorId = &get("<destructor>");
- return *DestructorId;
-}
-
-/// getConversionFunctionId - Return a placeholder identifier for a
-/// C++ conversion function.
-IdentifierInfo &IdentifierTable::getConversionFunctionId() {
- if (!ConversionFunctionId)
- ConversionFunctionId = &get("<conversion function>");
- return *ConversionFunctionId;
-}
+ : HashTable(8192) { }
//===----------------------------------------------------------------------===//
// Language Keyword Implementation
// a normal identifier.
if (getLang().CPlusPlus &&
Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope))
- D.SetConstructor(Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope),
- &PP.getIdentifierTable().getConstructorId(),
+ D.setConstructor(Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope),
Tok.getLocation());
else
D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
SourceLocation TildeLoc = ConsumeToken();
if (Tok.is(tok::identifier)) {
if (TypeTy *Type = ParseClassName())
- D.SetDestructor(Type, &PP.getIdentifierTable().getDestructorId(),
- TildeLoc);
+ D.setDestructor(Type, TildeLoc);
else
D.SetIdentifier(0, TildeLoc);
} else {
} else {
// This must be a conversion function (C++ [class.conv.fct]).
if (TypeTy *ConvType = ParseConversionFunctionId()) {
- D.SetConversionFunction(ConvType,
- &PP.getIdentifierTable().getConversionFunctionId(),
- OperatorLoc);
+ D.setConversionFunction(ConvType, OperatorLoc);
}
}
} else if (Tok.is(tok::l_paren) && SS.isEmpty()) {
// Parse the first declarator.
ParseDeclarator(DeclaratorInfo);
// Error parsing the declarator?
- if (DeclaratorInfo.getIdentifier() == 0) {
+ if (!DeclaratorInfo.hasName()) {
// If so, skip until the semi-colon or a }.
SkipUntil(tok::r_brace, true);
if (Tok.is(tok::semi))
Declarator DeclaratorInfo(DS, Declarator::FileContext);
ParseDeclarator(DeclaratorInfo);
// Error parsing the declarator?
- if (DeclaratorInfo.getIdentifier() == 0) {
+ if (!DeclaratorInfo.hasName()) {
// If so, skip until the semi-colon or a }.
SkipUntil(tok::r_brace, true);
if (Tok.is(tok::semi))
QualType ConvertDeclSpecToType(const DeclSpec &DS);
void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
QualType GetTypeForDeclarator(Declarator &D, Scope *S);
-
+ DeclarationName GetNameForDeclarator(Declarator &D);
+
QualType ObjCGetTypeForMethodDefinition(DeclTy *D);
bool UnwrapSimilarPointerTypes(QualType& T1, QualType& T2);
return CheckInitList.HadError();
}
+/// GetNameForDeclarator - Determine the full declaration name for the
+/// given Declarator.
+DeclarationName Sema::GetNameForDeclarator(Declarator &D) {
+ switch (D.getKind()) {
+ case Declarator::DK_Abstract:
+ assert(D.getIdentifier() == 0 && "abstract declarators have no name");
+ return DeclarationName();
+
+ case Declarator::DK_Normal:
+ assert (D.getIdentifier() != 0 && "normal declarators have an identifier");
+ return DeclarationName(D.getIdentifier());
+
+ case Declarator::DK_Constructor: {
+ QualType Ty = Context.getTypeDeclType((TypeDecl *)D.getDeclaratorIdType());
+ Ty = Context.getCanonicalType(Ty);
+ return Context.DeclarationNames.getCXXConstructorName(Ty);
+ }
+
+ case Declarator::DK_Destructor: {
+ QualType Ty = Context.getTypeDeclType((TypeDecl *)D.getDeclaratorIdType());
+ Ty = Context.getCanonicalType(Ty);
+ return Context.DeclarationNames.getCXXDestructorName(Ty);
+ }
+
+ case Declarator::DK_Conversion: {
+ QualType Ty = QualType::getFromOpaquePtr(D.getDeclaratorIdType());
+ Ty = Context.getCanonicalType(Ty);
+ return Context.DeclarationNames.getCXXConversionFunctionName(Ty);
+ }
+ }
+
+ assert(false && "Unknown name kind");
+ return DeclarationName();
+}
+
Sema::DeclTy *
Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
ScopedDecl *LastDeclarator = dyn_cast_or_null<ScopedDecl>((Decl *)lastDecl);
- IdentifierInfo *II = D.getIdentifier();
-
+ DeclarationName Name = GetNameForDeclarator(D);
+
// All of these full declarators require an identifier. If it doesn't have
// one, the ParsedFreeStandingDeclSpec action should be used.
- if (II == 0) {
+ if (!Name) {
if (!D.getInvalidType()) // Reject this if we think it is valid.
Diag(D.getDeclSpec().getSourceRange().getBegin(),
diag::err_declarator_need_ident,
// See if this is a redefinition of a variable in the same scope.
if (!D.getCXXScopeSpec().isSet()) {
DC = CurContext;
- PrevDecl = LookupDecl(II, Decl::IDNS_Ordinary, S);
+ PrevDecl = LookupDecl(Name, Decl::IDNS_Ordinary, S);
} else { // Something like "int foo::x;"
DC = static_cast<DeclContext*>(D.getCXXScopeSpec().getScopeRep());
- PrevDecl = LookupDecl(II, Decl::IDNS_Ordinary, S, DC);
+ PrevDecl = LookupDecl(Name, Decl::IDNS_Ordinary, S, DC);
// C++ 7.3.1.2p2:
// Members (including explicit specializations of templates) of a named
if (PrevDecl == 0) {
// No previous declaration in the qualifying scope.
Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member,
- II->getName(), D.getCXXScopeSpec().getRange());
+ Name.getAsString(), D.getCXXScopeSpec().getRange());
} else if (!CurContext->Encloses(DC)) {
// The qualifying scope doesn't enclose the original declaration.
// Emit diagnostic based on current scope.
SourceLocation L = D.getIdentifierLoc();
SourceRange R = D.getCXXScopeSpec().getRange();
if (isa<FunctionDecl>(CurContext)) {
- Diag(L, diag::err_invalid_declarator_in_function, II->getName(), R);
+ Diag(L, diag::err_invalid_declarator_in_function, Name.getAsString(),
+ R);
} else {
- Diag(L, diag::err_invalid_declarator_scope, II->getName(),
+ Diag(L, diag::err_invalid_declarator_scope, Name.getAsString(),
cast<NamedDecl>(DC)->getName(), R);
}
}
bool isInvalidDecl = CheckConstructorDeclarator(D, R, SC);
// Create the new declaration
- QualType ClassType = Context.getTypeDeclType(cast<CXXRecordDecl>(DC));
- ClassType = Context.getCanonicalType(ClassType);
- DeclarationName ConName
- = Context.DeclarationNames.getCXXConstructorName(ClassType);
NewFD = CXXConstructorDecl::Create(Context,
cast<CXXRecordDecl>(DC),
- D.getIdentifierLoc(), ConName, R,
+ D.getIdentifierLoc(), Name, R,
isExplicit, isInline,
/*isImplicitlyDeclared=*/false);
if (DC->isCXXRecord()) {
bool isInvalidDecl = CheckDestructorDeclarator(D, R, SC);
- QualType ClassType = Context.getTypeDeclType(cast<CXXRecordDecl>(DC));
- ClassType = Context.getCanonicalType(ClassType);
- DeclarationName DesName
- = Context.DeclarationNames.getCXXDestructorName(ClassType);
-
NewFD = CXXDestructorDecl::Create(Context,
cast<CXXRecordDecl>(DC),
- D.getIdentifierLoc(), DesName, R,
+ D.getIdentifierLoc(), Name, R,
isInline,
/*isImplicitlyDeclared=*/false);
// Create a FunctionDecl to satisfy the function definition parsing
// code path.
NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(),
- II, R, SC, isInline, LastDeclarator,
+ Name, R, SC, isInline, LastDeclarator,
// FIXME: Move to DeclGroup...
D.getDeclSpec().getSourceRange().getBegin());
NewFD->setInvalidDecl();
} else {
bool isInvalidDecl = CheckConversionDeclarator(D, R, SC);
- QualType ConvType = R->getAsFunctionType()->getResultType();
- ConvType = Context.getCanonicalType(ConvType);
- DeclarationName ConvName
- = Context.DeclarationNames.getCXXConversionFunctionName(ConvType);
-
NewFD = CXXConversionDecl::Create(Context,
cast<CXXRecordDecl>(DC),
- D.getIdentifierLoc(), ConvName, R,
+ D.getIdentifierLoc(), Name, R,
isInline, isExplicit);
if (isInvalidDecl)
} else if (DC->isCXXRecord()) {
// This is a C++ method declaration.
NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
- D.getIdentifierLoc(), II, R,
+ D.getIdentifierLoc(), Name, R,
(SC == FunctionDecl::Static), isInline,
LastDeclarator);
} else {
NewFD = FunctionDecl::Create(Context, DC,
D.getIdentifierLoc(),
- II, R, SC, isInline, LastDeclarator,
+ Name, R, SC, isInline, LastDeclarator,
// FIXME: Move to DeclGroup...
D.getDeclSpec().getSourceRange().getBegin());
}
Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember);
InvalidDecl = true;
}
+
+ IdentifierInfo *II = Name.getAsIdentifierInfo();
+ if (!II) {
+ Diag(D.getIdentifierLoc(), diag::err_bad_variable_name,
+ Name.getAsString());
+ return 0;
+ }
+
if (DC->isCXXRecord()) {
assert(SC == VarDecl::Static && "Invalid storage class for member!");
// This is a static data member for a C++ class.
New->setLexicalDeclContext(CurContext);
// If this has an identifier, add it to the scope stack.
- if (II)
+ if (Name)
PushOnScopeChains(New, S);
// If any semantic error occurred, mark the decl as invalid.
if (D.getInvalidType() || InvalidDecl)
ExprTy *BW, ExprTy *InitExpr,
DeclTy *LastInGroup) {
const DeclSpec &DS = D.getDeclSpec();
- IdentifierInfo *II = D.getIdentifier();
+ DeclarationName Name = GetNameForDeclarator(D);
Expr *BitWidth = static_cast<Expr*>(BW);
Expr *Init = static_cast<Expr*>(InitExpr);
SourceLocation Loc = D.getIdentifierLoc();
if (!Member) return LastInGroup;
- assert((II || isInstField) && "No identifier for non-field ?");
+ assert((Name || isInstField) && "No identifier for non-field ?");
// set/getAccess is not part of Decl's interface to avoid bloating it with C++
// specific methods. Use a wrapper class that can be used with all C++ class
// FIXME: Emit diagnostic about only constructors taking base initializers
// or something similar, when constructor support is in place.
Diag(Loc, diag::err_not_bitfield_type,
- II->getName(), BitWidth->getSourceRange());
+ Name.getAsString(), BitWidth->getSourceRange());
InvalidDecl = true;
} else if (isInstField) {
// C++ 9.6p3: A bit-field shall have integral or enumeration type.
if (!cast<FieldDecl>(Member)->getType()->isIntegralType()) {
Diag(Loc, diag::err_not_integral_type_bitfield,
- II->getName(), BitWidth->getSourceRange());
+ Name.getAsString(), BitWidth->getSourceRange());
InvalidDecl = true;
}
// A function typedef ("typedef int f(); f a;").
// C++ 9.6p3: A bit-field shall have integral or enumeration type.
Diag(Loc, diag::err_not_integral_type_bitfield,
- II->getName(), BitWidth->getSourceRange());
+ Name.getAsString(), BitWidth->getSourceRange());
InvalidDecl = true;
} else if (isa<TypedefDecl>(Member)) {
// "cannot declare 'A' to be a bit-field type"
- Diag(Loc, diag::err_not_bitfield_type, II->getName(),
+ Diag(Loc, diag::err_not_bitfield_type, Name.getAsString(),
BitWidth->getSourceRange());
InvalidDecl = true;
"Didn't we cover all member kinds?");
// C++ 9.6p3: A bit-field shall not be a static member.
// "static member 'A' cannot be a bit-field"
- Diag(Loc, diag::err_static_not_bitfield, II->getName(),
+ Diag(Loc, diag::err_static_not_bitfield, Name.getAsString(),
BitWidth->getSourceRange());
InvalidDecl = true;
}
} else {
// not const integral.
Diag(Loc, diag::err_member_initialization,
- II->getName(), Init->getSourceRange());
+ Name.getAsString(), Init->getSourceRange());
InvalidDecl = true;
}
} else {
// not static member.
Diag(Loc, diag::err_member_initialization,
- II->getName(), Init->getSourceRange());
+ Name.getAsString(), Init->getSourceRange());
InvalidDecl = true;
}
}
operator int(); // expected-error{{conversion function must be a non-static member function}}
+operator int; // expected-error{{'operator int' cannot be the name of a variable or data member}}
+
typedef int func_type(int);
typedef int array_type[10];
x = operator+(x, x);
}
-X operator+(int, float); // expected-error{{overloaded 'operator+' must have at least one parameter of class or enumeration type}}
+X operator+(int, float); // expected-error{{overloaded 'operator+' must have at least one parameter of class or enumeration type}} \
+ // expected-error{{previous definition is here}}
X operator*(X, X = 5); // expected-error{{parameter of overloaded 'operator*' cannot have a default argument}}
Y& operator++(Y&);
Y operator++(Y&, INT);
X operator++(X&, FLOAT); // expected-error{{parameter of overloaded post-increment operator must have type 'int' (not 'float')}}
+
+int operator+; // expected-error{{redefinition of 'operator+' as different kind of symbol}}