From 802a030d6e7df7c9d8ecc37d1b9dd3bea3c9f1f1 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 31 Jul 2009 05:24:01 +0000 Subject: [PATCH] Canonicalization and profiling for overloaded function declarations, for those extra-esoteric cases. Not that any two given C++ compilers agree on this test case, but this change gives us a strong definition of equivalent types. llvm-svn: 77664 --- clang/lib/AST/ASTContext.cpp | 22 ++++++++++++++++++--- clang/lib/AST/StmtProfile.cpp | 26 +++++++++++++++++++++++-- clang/test/SemaTemplate/canonical-expr-type.cpp | 17 ++++++++++++++++ 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 1b73679..c474084 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2118,9 +2118,25 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) { // If this template name refers to a set of overloaded function templates, /// the canonical template name merely stores the set of function templates. - if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl()) - // FIXME: Can't really canonicalize a set of overloaded functions, can we? - return TemplateName(Ovl); + if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl()) { + OverloadedFunctionDecl *CanonOvl = 0; + for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(), + FEnd = Ovl->function_end(); + F != FEnd; ++F) { + Decl *Canon = F->get()->getCanonicalDecl(); + if (CanonOvl || Canon != F->get()) { + if (!CanonOvl) + CanonOvl = OverloadedFunctionDecl::Create(*this, + Ovl->getDeclContext(), + Ovl->getDeclName()); + + CanonOvl->addOverload( + AnyFunctionDecl::getFromNamedDecl(cast(Canon))); + } + } + + return TemplateName(CanonOvl? CanonOvl : Ovl); + } DependentTemplateName *DTN = Name.getAsDependentTemplateName(); assert(DTN && "Non-dependent template names must refer to template decls."); diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 8039d97..5714c68 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -603,8 +603,7 @@ void StmtProfiler::VisitObjCIsaExpr(ObjCIsaExpr *S) { void StmtProfiler::VisitDecl(Decl *D) { if (Canonical && D) { - if (NonTypeTemplateParmDecl *NTTP - = dyn_cast(D)) { + if (NonTypeTemplateParmDecl *NTTP = dyn_cast(D)) { ID.AddInteger(NTTP->getDepth()); ID.AddInteger(NTTP->getIndex()); VisitType(NTTP->getType()); @@ -612,6 +611,29 @@ void StmtProfiler::VisitDecl(Decl *D) { } // FIXME: Template template parameters? + + if (OverloadedFunctionDecl *Ovl = dyn_cast(D)) { + // Canonicalize all of the function declarations within the overload + // set. + llvm::SmallVector Functions; + for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(), + FEnd = Ovl->function_end(); + F != FEnd; ++F) + Functions.push_back(F->get()->getCanonicalDecl()); + + // Sorting the functions based on the point means that the ID generated + // will be different from one execution of the compiler to another. + // Since these IDs don't persist over time, the change in ordering will + // not affect compilation. + std::sort(Functions.begin(), Functions.end()); + + for (llvm::SmallVector::iterator F = Functions.begin(), + FEnd = Functions.end(); + F != FEnd; ++F) + VisitDecl(*F); + + return; + } } ID.AddPointer(D? D->getCanonicalDecl() : 0); diff --git a/clang/test/SemaTemplate/canonical-expr-type.cpp b/clang/test/SemaTemplate/canonical-expr-type.cpp index 48147f0..f8cc57b 100644 --- a/clang/test/SemaTemplate/canonical-expr-type.cpp +++ b/clang/test/SemaTemplate/canonical-expr-type.cpp @@ -15,6 +15,23 @@ void f0(T x, __typeof__((f)(N)) y) { } template void f0(U u, __typeof__(f(M))) { } // expected-error{{redefinition}} +// Test insane typeof(expr) overload set canonicalization +void f(int); +void f(double); + +template +void f0a(T x, __typeof__(f(N)) y) { } // expected-note{{previous}} + +void f(int); + +template +void f0a(T x, __typeof__(f(N)) y) { } // expected-error{{redefinition}} + +void f(float); + +template +void f0a(T x, __typeof__(f(N)) y) { } + // Test dependently-sized array canonicalization template void f1(T (&array)[N + M]) { } // expected-note{{previous}} -- 2.7.4