summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp62
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp39
-rw-r--r--clang/test/Modules/Inputs/redecl-merge-left.h4
-rw-r--r--clang/test/Modules/Inputs/redecl-merge-right.h7
-rw-r--r--clang/test/Modules/redecl-merge.m8
5 files changed, 76 insertions, 44 deletions
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index c00b69cf75b..c34243f6016 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -490,14 +490,38 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
}
void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
- VisitRedeclarable(FD);
+ // Record the declaration -> global ID mapping.
+ Reader.DeclToID[FD] = ThisDeclID;
+
+ RedeclarableResult Redecl = VisitRedeclarable(FD);
VisitDeclaratorDecl(FD);
ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName(), Record, Idx);
FD->IdentifierNamespace = Record[Idx++];
+
+ // FunctionDecl's body is handled last at ASTDeclReader::Visit,
+ // after everything else is read.
+
+ FD->SClass = (StorageClass)Record[Idx++];
+ FD->SClassAsWritten = (StorageClass)Record[Idx++];
+ FD->IsInline = Record[Idx++];
+ FD->IsInlineSpecified = Record[Idx++];
+ FD->IsVirtualAsWritten = Record[Idx++];
+ FD->IsPure = Record[Idx++];
+ FD->HasInheritedPrototype = Record[Idx++];
+ FD->HasWrittenPrototype = Record[Idx++];
+ FD->IsDeleted = Record[Idx++];
+ FD->IsTrivial = Record[Idx++];
+ FD->IsDefaulted = Record[Idx++];
+ FD->IsExplicitlyDefaulted = Record[Idx++];
+ FD->HasImplicitReturnZero = Record[Idx++];
+ FD->IsConstexpr = Record[Idx++];
+ FD->EndRangeLoc = ReadSourceLocation(Record, Idx);
+
switch ((FunctionDecl::TemplatedKind)Record[Idx++]) {
default: llvm_unreachable("Unhandled TemplatedKind!");
case FunctionDecl::TK_NonTemplate:
+ mergeRedeclarable(FD, Redecl);
break;
case FunctionDecl::TK_FunctionTemplate:
FD->setDescribedFunctionTemplate(ReadDeclAs<FunctionTemplateDecl>(Record,
@@ -591,25 +615,6 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
}
}
- // FunctionDecl's body is handled last at ASTDeclReader::Visit,
- // after everything else is read.
-
- FD->SClass = (StorageClass)Record[Idx++];
- FD->SClassAsWritten = (StorageClass)Record[Idx++];
- FD->IsInline = Record[Idx++];
- FD->IsInlineSpecified = Record[Idx++];
- FD->IsVirtualAsWritten = Record[Idx++];
- FD->IsPure = Record[Idx++];
- FD->HasInheritedPrototype = Record[Idx++];
- FD->HasWrittenPrototype = Record[Idx++];
- FD->IsDeleted = Record[Idx++];
- FD->IsTrivial = Record[Idx++];
- FD->IsDefaulted = Record[Idx++];
- FD->IsExplicitlyDefaulted = Record[Idx++];
- FD->HasImplicitReturnZero = Record[Idx++];
- FD->IsConstexpr = Record[Idx++];
- FD->EndRangeLoc = ReadSourceLocation(Record, Idx);
-
// Read in the parameters.
unsigned NumParams = Record[Idx++];
SmallVector<ParmVarDecl *, 16> Params;
@@ -1696,12 +1701,19 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
// Compatible tags match.
if (TagDecl *TagX = dyn_cast<TagDecl>(X)) {
TagDecl *TagY = cast<TagDecl>(Y);
- if ((TagX->getTagKind() == TagY->getTagKind()) ||
- ((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class)&&
- (TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class)))
- return true;
+ return (TagX->getTagKind() == TagY->getTagKind()) ||
+ ((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class) &&
+ (TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class));
}
-
+
+ // Functions with the same type and linkage match.
+ if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) {
+ FunctionDecl *FuncY = cast<FunctionDecl>(Y);
+ return (FuncX->getLinkage() == FuncY->getLinkage()) &&
+ FuncX->getASTContext().hasSameType(FuncX->getType(), FuncY->getType());
+ }
+
+
// FIXME: Many other cases to implement.
return false;
}
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index a995e37ee7b..f6c65f0870b 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -302,6 +302,26 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record);
Record.push_back(D->getIdentifierNamespace());
+
+ // FunctionDecl's body is handled last at ASTWriterDecl::Visit,
+ // after everything else is written.
+
+ Record.push_back(D->getStorageClass()); // FIXME: stable encoding
+ Record.push_back(D->getStorageClassAsWritten());
+ Record.push_back(D->IsInline);
+ Record.push_back(D->isInlineSpecified());
+ Record.push_back(D->isVirtualAsWritten());
+ Record.push_back(D->isPure());
+ Record.push_back(D->hasInheritedPrototype());
+ Record.push_back(D->hasWrittenPrototype());
+ Record.push_back(D->isDeletedAsWritten());
+ Record.push_back(D->isTrivial());
+ Record.push_back(D->isDefaulted());
+ Record.push_back(D->isExplicitlyDefaulted());
+ Record.push_back(D->hasImplicitReturnZero());
+ Record.push_back(D->isConstexpr());
+ Writer.AddSourceLocation(D->getLocEnd(), Record);
+
Record.push_back(D->getTemplatedKind());
switch (D->getTemplatedKind()) {
default: llvm_unreachable("Unhandled TemplatedKind!");
@@ -368,25 +388,6 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
}
}
- // FunctionDecl's body is handled last at ASTWriterDecl::Visit,
- // after everything else is written.
-
- Record.push_back(D->getStorageClass()); // FIXME: stable encoding
- Record.push_back(D->getStorageClassAsWritten());
- Record.push_back(D->IsInline);
- Record.push_back(D->isInlineSpecified());
- Record.push_back(D->isVirtualAsWritten());
- Record.push_back(D->isPure());
- Record.push_back(D->hasInheritedPrototype());
- Record.push_back(D->hasWrittenPrototype());
- Record.push_back(D->isDeletedAsWritten());
- Record.push_back(D->isTrivial());
- Record.push_back(D->isDefaulted());
- Record.push_back(D->isExplicitlyDefaulted());
- Record.push_back(D->hasImplicitReturnZero());
- Record.push_back(D->isConstexpr());
- Writer.AddSourceLocation(D->getLocEnd(), Record);
-
Record.push_back(D->param_size());
for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
P != PEnd; ++P)
diff --git a/clang/test/Modules/Inputs/redecl-merge-left.h b/clang/test/Modules/Inputs/redecl-merge-left.h
index 47f3492f309..3eb0a735fa9 100644
--- a/clang/test/Modules/Inputs/redecl-merge-left.h
+++ b/clang/test/Modules/Inputs/redecl-merge-left.h
@@ -59,6 +59,10 @@ void consume_S4(struct S4*);
typedef int T1;
typedef float T2;
+int func0(int);
+int func1(int);
+int func2(int);
+
#ifdef __cplusplus
template<typename T> class Vector;
diff --git a/clang/test/Modules/Inputs/redecl-merge-right.h b/clang/test/Modules/Inputs/redecl-merge-right.h
index 315a9c37fff..9660199c72d 100644
--- a/clang/test/Modules/Inputs/redecl-merge-right.h
+++ b/clang/test/Modules/Inputs/redecl-merge-right.h
@@ -62,6 +62,13 @@ struct S4 *produce_S4(void);
typedef int T1;
typedef double T2;
+int func0(int);
+int func1(int);
+int func1(int);
+int func1(int);
+int func1(int);
+static int func2(int);
+
#ifdef __cplusplus
template<typename T> class Vector {
public:
diff --git a/clang/test/Modules/redecl-merge.m b/clang/test/Modules/redecl-merge.m
index 44d427c4c75..b8752610fb4 100644
--- a/clang/test/Modules/redecl-merge.m
+++ b/clang/test/Modules/redecl-merge.m
@@ -61,9 +61,17 @@ void testTypedefMerge(int i, double d) {
// FIXME: Typedefs aren't actually merged in the sense of other merges, because
// we should only merge them when the types are identical.
// in other file: expected-note{{candidate found by name lookup is 'T2'}}
+ // in other file: expected-note{{candidate function}}
T2 *dp = &d; // expected-error{{reference to 'T2' is ambiguous}}
}
+void testFuncMerge(int i) {
+ func0(i);
+ // in other file: expected-note{{candidate function}}
+ func1(i);
+ func2(i); // expected-error{{call to 'func2' is ambiguous}}
+}
+
// Test redeclarations of entities in explicit submodules, to make
// sure we're maintaining the declaration chains even when normal name
// lookup can't see what we're looking for.
OpenPOWER on IntegriCloud