mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-29 10:36:06 +00:00
When a function with a prototype is redeclared without a prototype,
merge the prototype into the redeclaration (and make a note in the declaration). Fixes PR3588. llvm-svn: 64641
This commit is contained in:
parent
a1c37501ed
commit
bcbf86399f
@ -535,6 +535,7 @@ private:
|
||||
bool IsInline : 1;
|
||||
bool IsVirtual : 1;
|
||||
bool IsPure : 1;
|
||||
bool InheritedPrototype : 1;
|
||||
|
||||
// Move to DeclGroup when it is implemented.
|
||||
SourceLocation TypeSpecStartLoc;
|
||||
@ -547,7 +548,7 @@ protected:
|
||||
DeclContext(DK),
|
||||
ParamInfo(0), Body(0), PreviousDeclaration(0),
|
||||
SClass(S), IsInline(isInline), IsVirtual(false), IsPure(false),
|
||||
TypeSpecStartLoc(TSSL) {}
|
||||
InheritedPrototype(false), TypeSpecStartLoc(TSSL) {}
|
||||
|
||||
virtual ~FunctionDecl() {}
|
||||
virtual void Destroy(ASTContext& C);
|
||||
@ -590,6 +591,11 @@ public:
|
||||
bool isPure() { return IsPure; }
|
||||
void setPure() { IsPure = true; }
|
||||
|
||||
/// \brief Whether this function inherited its prototype from a
|
||||
/// previous declaration.
|
||||
bool inheritedPrototype() { return InheritedPrototype; }
|
||||
void setInheritedPrototype() { InheritedPrototype = true; }
|
||||
|
||||
/// getPreviousDeclaration - Return the previous declaration of this
|
||||
/// function.
|
||||
const FunctionDecl *getPreviousDeclaration() const {
|
||||
|
@ -593,7 +593,24 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
|
||||
// duplicate function decls like "void f(int); void f(enum X);" properly.
|
||||
if (!getLangOptions().CPlusPlus &&
|
||||
Context.typesAreCompatible(OldQType, NewQType)) {
|
||||
const FunctionType *NewFuncType = NewQType->getAsFunctionType();
|
||||
const FunctionTypeProto *OldProto = 0;
|
||||
if (isa<FunctionTypeNoProto>(NewFuncType) &&
|
||||
(OldProto = OldQType->getAsFunctionTypeProto())) {
|
||||
// The old declaration provided a function prototype, but the
|
||||
// new declaration does not. Merge in the prototype.
|
||||
llvm::SmallVector<QualType, 16> ParamTypes(OldProto->arg_type_begin(),
|
||||
OldProto->arg_type_end());
|
||||
NewQType = Context.getFunctionType(NewFuncType->getResultType(),
|
||||
&ParamTypes[0], ParamTypes.size(),
|
||||
OldProto->isVariadic(),
|
||||
OldProto->getTypeQuals());
|
||||
New->setType(NewQType);
|
||||
New->setInheritedPrototype();
|
||||
}
|
||||
|
||||
MergeAttributes(New, Old);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
30
clang/test/Sema/function-redecl.c
Normal file
30
clang/test/Sema/function-redecl.c
Normal file
@ -0,0 +1,30 @@
|
||||
// RUN: clang -fsyntax-only -verify %s
|
||||
|
||||
// PR3588
|
||||
void g0(int, int);
|
||||
void g0(); // expected-note{{previous declaration is here}}
|
||||
|
||||
void f0() {
|
||||
g0(1, 2, 3); // expected-error{{too many arguments to function call}}
|
||||
}
|
||||
|
||||
void g0(int); // expected-error{{conflicting types for 'g0'}}
|
||||
|
||||
int g1(int, int);
|
||||
|
||||
typedef int INT;
|
||||
|
||||
INT g1(x, y)
|
||||
int x;
|
||||
int y;
|
||||
{
|
||||
return x + y;
|
||||
}
|
||||
|
||||
int g2(int, int); // expected-note{{previous declaration is here}}
|
||||
|
||||
INT g2(x) // expected-error{{conflicting types for 'g2'}}
|
||||
int x;
|
||||
{
|
||||
return x;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user