diff options
| -rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 62 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 39 | ||||
| -rw-r--r-- | clang/test/Modules/Inputs/redecl-merge-left.h | 4 | ||||
| -rw-r--r-- | clang/test/Modules/Inputs/redecl-merge-right.h | 7 | ||||
| -rw-r--r-- | clang/test/Modules/redecl-merge.m | 8 |
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. |

