llvm-capstone/clang/lib/AST/Decl.cpp

1717 lines
59 KiB
C++
Raw Normal View History

//===--- Decl.cpp - Declaration AST Node Implementation -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Decl subclasses.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
//===----------------------------------------------------------------------===//
// NamedDecl Implementation
//===----------------------------------------------------------------------===//
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
/// \brief Get the most restrictive linkage for the types in the given
/// template parameter list.
static Linkage
getLinkageForTemplateParameterList(const TemplateParameterList *Params) {
Linkage L = ExternalLinkage;
for (TemplateParameterList::const_iterator P = Params->begin(),
PEnd = Params->end();
P != PEnd; ++P) {
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P))
if (!NTTP->getType()->isDependentType()) {
L = minLinkage(L, NTTP->getType()->getLinkage());
continue;
}
if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(*P)) {
L = minLinkage(L,
getLinkageForTemplateParameterList(TTP->getTemplateParameters()));
}
}
return L;
}
/// \brief Get the most restrictive linkage for the types and
/// declarations in the given template argument list.
static Linkage getLinkageForTemplateArgumentList(const TemplateArgument *Args,
unsigned NumArgs) {
Linkage L = ExternalLinkage;
for (unsigned I = 0; I != NumArgs; ++I) {
switch (Args[I].getKind()) {
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Expression:
break;
case TemplateArgument::Type:
L = minLinkage(L, Args[I].getAsType()->getLinkage());
break;
case TemplateArgument::Declaration:
if (NamedDecl *ND = dyn_cast<NamedDecl>(Args[I].getAsDecl()))
L = minLinkage(L, ND->getLinkage());
if (ValueDecl *VD = dyn_cast<ValueDecl>(Args[I].getAsDecl()))
L = minLinkage(L, VD->getType()->getLinkage());
break;
case TemplateArgument::Template:
if (TemplateDecl *Template
= Args[I].getAsTemplate().getAsTemplateDecl())
L = minLinkage(L, Template->getLinkage());
break;
case TemplateArgument::Pack:
L = minLinkage(L,
getLinkageForTemplateArgumentList(Args[I].pack_begin(),
Args[I].pack_size()));
break;
}
}
return L;
}
static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
assert(D->getDeclContext()->getLookupContext()->isFileContext() &&
"Not a name having namespace scope");
ASTContext &Context = D->getASTContext();
// C++ [basic.link]p3:
// A name having namespace scope (3.3.6) has internal linkage if it
// is the name of
// - an object, reference, function or function template that is
// explicitly declared static; or,
// (This bullet corresponds to C99 6.2.2p3.)
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
// Explicitly declared static.
if (Var->getStorageClass() == VarDecl::Static)
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
return InternalLinkage;
// - an object or reference that is explicitly declared const
// and neither explicitly declared extern nor previously
// declared to have external linkage; or
// (there is no equivalent in C99)
if (Context.getLangOptions().CPlusPlus &&
Var->getType().isConstant(Context) &&
Var->getStorageClass() != VarDecl::Extern &&
Var->getStorageClass() != VarDecl::PrivateExtern) {
bool FoundExtern = false;
for (const VarDecl *PrevVar = Var->getPreviousDeclaration();
PrevVar && !FoundExtern;
PrevVar = PrevVar->getPreviousDeclaration())
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
if (isExternalLinkage(PrevVar->getLinkage()))
FoundExtern = true;
if (!FoundExtern)
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
return InternalLinkage;
}
} else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) {
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
// C++ [temp]p4:
// A non-member function template can have internal linkage; any
// other template name shall have external linkage.
const FunctionDecl *Function = 0;
if (const FunctionTemplateDecl *FunTmpl
= dyn_cast<FunctionTemplateDecl>(D))
Function = FunTmpl->getTemplatedDecl();
else
Function = cast<FunctionDecl>(D);
// Explicitly declared static.
if (Function->getStorageClass() == FunctionDecl::Static)
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
return InternalLinkage;
} else if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) {
// - a data member of an anonymous union.
if (cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion())
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
return InternalLinkage;
}
// C++ [basic.link]p4:
// A name having namespace scope has external linkage if it is the
// name of
//
// - an object or reference, unless it has internal linkage; or
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
if (!Context.getLangOptions().CPlusPlus &&
(Var->getStorageClass() == VarDecl::Extern ||
Var->getStorageClass() == VarDecl::PrivateExtern)) {
// C99 6.2.2p4:
// For an identifier declared with the storage-class specifier
// extern in a scope in which a prior declaration of that
// identifier is visible, if the prior declaration specifies
// internal or external linkage, the linkage of the identifier
// at the later declaration is the same as the linkage
// specified at the prior declaration. If no prior declaration
// is visible, or if the prior declaration specifies no
// linkage, then the identifier has external linkage.
if (const VarDecl *PrevVar = Var->getPreviousDeclaration()) {
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
if (Linkage L = PrevVar->getLinkage())
return L;
}
}
// C99 6.2.2p5:
// If the declaration of an identifier for an object has file
// scope and no storage-class specifier, its linkage is
// external.
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
if (Var->isInAnonymousNamespace())
return UniqueExternalLinkage;
return ExternalLinkage;
}
// - a function, unless it has internal linkage; or
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
// C99 6.2.2p5:
// If the declaration of an identifier for a function has no
// storage-class specifier, its linkage is determined exactly
// as if it were declared with the storage-class specifier
// extern.
if (!Context.getLangOptions().CPlusPlus &&
(Function->getStorageClass() == FunctionDecl::Extern ||
Function->getStorageClass() == FunctionDecl::PrivateExtern ||
Function->getStorageClass() == FunctionDecl::None)) {
// C99 6.2.2p4:
// For an identifier declared with the storage-class specifier
// extern in a scope in which a prior declaration of that
// identifier is visible, if the prior declaration specifies
// internal or external linkage, the linkage of the identifier
// at the later declaration is the same as the linkage
// specified at the prior declaration. If no prior declaration
// is visible, or if the prior declaration specifies no
// linkage, then the identifier has external linkage.
if (const FunctionDecl *PrevFunc = Function->getPreviousDeclaration()) {
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
if (Linkage L = PrevFunc->getLinkage())
return L;
}
}
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
if (Function->isInAnonymousNamespace())
return UniqueExternalLinkage;
if (FunctionTemplateSpecializationInfo *SpecInfo
= Function->getTemplateSpecializationInfo()) {
Linkage L = SpecInfo->getTemplate()->getLinkage();
const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments;
L = minLinkage(L,
getLinkageForTemplateArgumentList(
TemplateArgs.getFlatArgumentList(),
TemplateArgs.flat_size()));
return L;
}
return ExternalLinkage;
}
// - a named class (Clause 9), or an unnamed class defined in a
// typedef declaration in which the class has the typedef name
// for linkage purposes (7.1.3); or
// - a named enumeration (7.2), or an unnamed enumeration
// defined in a typedef declaration in which the enumeration
// has the typedef name for linkage purposes (7.1.3); or
if (const TagDecl *Tag = dyn_cast<TagDecl>(D))
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
if (Tag->getDeclName() || Tag->getTypedefForAnonDecl()) {
if (Tag->isInAnonymousNamespace())
return UniqueExternalLinkage;
// If this is a class template specialization, consider the
// linkage of the template and template arguments.
if (const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
Linkage L = getLinkageForTemplateArgumentList(
TemplateArgs.getFlatArgumentList(),
TemplateArgs.flat_size());
return minLinkage(L, Spec->getSpecializedTemplate()->getLinkage());
}
return ExternalLinkage;
}
// - an enumerator belonging to an enumeration with external linkage;
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
if (isa<EnumConstantDecl>(D)) {
Linkage L = cast<NamedDecl>(D->getDeclContext())->getLinkage();
if (isExternalLinkage(L))
return L;
}
// - a template, unless it is a function template that has
// internal linkage (Clause 14);
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
if (D->isInAnonymousNamespace())
return UniqueExternalLinkage;
return getLinkageForTemplateParameterList(
Template->getTemplateParameters());
}
// - a namespace (7.3), unless it is declared within an unnamed
// namespace.
if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace())
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
return ExternalLinkage;
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
return NoLinkage;
}
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
Linkage NamedDecl::getLinkage() const {
// Objective-C: treat all Objective-C declarations as having external
// linkage.
switch (getKind()) {
default:
break;
case Decl::ObjCAtDefsField:
case Decl::ObjCCategory:
case Decl::ObjCCategoryImpl:
case Decl::ObjCClass:
case Decl::ObjCCompatibleAlias:
case Decl::ObjCForwardProtocol:
case Decl::ObjCImplementation:
case Decl::ObjCInterface:
case Decl::ObjCIvar:
case Decl::ObjCMethod:
case Decl::ObjCProperty:
case Decl::ObjCPropertyImpl:
case Decl::ObjCProtocol:
return ExternalLinkage;
}
// Handle linkage for namespace-scope names.
if (getDeclContext()->getLookupContext()->isFileContext())
if (Linkage L = getLinkageForNamespaceScopeDecl(this))
return L;
// C++ [basic.link]p5:
// In addition, a member function, static data member, a named
// class or enumeration of class scope, or an unnamed class or
// enumeration defined in a class-scope typedef declaration such
// that the class or enumeration has the typedef name for linkage
// purposes (7.1.3), has external linkage if the name of the class
// has external linkage.
if (getDeclContext()->isRecord() &&
(isa<CXXMethodDecl>(this) || isa<VarDecl>(this) ||
(isa<TagDecl>(this) &&
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
(getDeclName() || cast<TagDecl>(this)->getTypedefForAnonDecl())))) {
Linkage L = cast<RecordDecl>(getDeclContext())->getLinkage();
if (isExternalLinkage(L))
return L;
}
// C++ [basic.link]p6:
// The name of a function declared in block scope and the name of
// an object declared by a block scope extern declaration have
// linkage. If there is a visible declaration of an entity with
// linkage having the same name and type, ignoring entities
// declared outside the innermost enclosing namespace scope, the
// block scope declaration declares that same entity and receives
// the linkage of the previous declaration. If there is more than
// one such matching entity, the program is ill-formed. Otherwise,
// if no matching entity is found, the block scope entity receives
// external linkage.
if (getLexicalDeclContext()->isFunctionOrMethod()) {
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this)) {
if (Function->getPreviousDeclaration())
if (Linkage L = Function->getPreviousDeclaration()->getLinkage())
return L;
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
if (Function->isInAnonymousNamespace())
return UniqueExternalLinkage;
return ExternalLinkage;
}
if (const VarDecl *Var = dyn_cast<VarDecl>(this))
if (Var->getStorageClass() == VarDecl::Extern ||
Var->getStorageClass() == VarDecl::PrivateExtern) {
if (Var->getPreviousDeclaration())
if (Linkage L = Var->getPreviousDeclaration()->getLinkage())
return L;
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
if (Var->isInAnonymousNamespace())
return UniqueExternalLinkage;
return ExternalLinkage;
}
}
// C++ [basic.link]p6:
// Names not covered by these rules have no linkage.
return NoLinkage;
When a function or variable somehow depends on a type or declaration that is in an anonymous namespace, give that function or variable internal linkage. This change models an oddity of the C++ standard, where names declared in an anonymous namespace have external linkage but, because anonymous namespace are really "uniquely-named" namespaces, the names cannot be referenced from other translation units. That means that they have external linkage for semantic analysis, but the only sensible implementation for code generation is to give them internal linkage. We now model this notion via the UniqueExternalLinkage linkage type. There are several changes here: - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage when the declaration is in an anonymous namespace. - Added Type::getLinkage() to determine the linkage of a type, which is defined as the minimum linkage of the types (when we're dealing with a compound type that is not a struct/class/union). - Extended NamedDecl::getLinkage() to consider the linkage of the template arguments and template parameters of function template specializations and class template specializations. - Taught code generation to rely on NamedDecl::getLinkage() when determining the linkage of variables and functions, also considering the linkage of the types of those variables and functions (C++ only). Map UniqueExternalLinkage to internal linkage, taking out the explicit checks for isInAnonymousNamespace(). This fixes much of PR5792, which, as discovered by Anders Carlsson, is actually the reason behind the pass-manager assertion that causes the majority of clang-on-clang regression test failures. With this fix, Clang-built-Clang+LLVM passes 88% of its regression tests (up from 67%). The specific numbers are: LLVM: Expected Passes : 4006 Expected Failures : 32 Unsupported Tests : 40 Unexpected Failures: 736 Clang: Expected Passes : 1903 Expected Failures : 14 Unexpected Failures: 75 Overall: Expected Passes : 5909 Expected Failures : 46 Unsupported Tests : 40 Unexpected Failures: 811 Still to do: - Improve testing - Check whether we should allow the presence of types with InternalLinkage (in addition to UniqueExternalLinkage) given variables/functions internal linkage in C++, as mentioned in PR5792. - Determine how expensive the getLinkage() calls are in practice; consider caching the result in NamedDecl. - Assess the feasibility of Chris's idea in comment #1 of PR5792. llvm-svn: 95216
2010-02-03 09:33:45 +00:00
}
std::string NamedDecl::getQualifiedNameAsString() const {
return getQualifiedNameAsString(getASTContext().getLangOptions());
}
std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
const DeclContext *Ctx = getDeclContext();
if (Ctx->isFunctionOrMethod())
return getNameAsString();
typedef llvm::SmallVector<const DeclContext *, 8> ContextsTy;
ContextsTy Contexts;
// Collect contexts.
while (Ctx && isa<NamedDecl>(Ctx)) {
Contexts.push_back(Ctx);
Ctx = Ctx->getParent();
};
std::string QualName;
llvm::raw_string_ostream OS(QualName);
for (ContextsTy::reverse_iterator I = Contexts.rbegin(), E = Contexts.rend();
I != E; ++I) {
if (const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(*I)) {
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
std::string TemplateArgsStr
= TemplateSpecializationType::PrintTemplateArgumentList(
TemplateArgs.getFlatArgumentList(),
TemplateArgs.flat_size(),
P);
OS << Spec->getName() << TemplateArgsStr;
} else if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(*I)) {
if (ND->isAnonymousNamespace())
OS << "<anonymous namespace>";
else
OS << ND;
} else if (const RecordDecl *RD = dyn_cast<RecordDecl>(*I)) {
if (!RD->getIdentifier())
OS << "<anonymous " << RD->getKindName() << '>';
else
OS << RD;
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
const FunctionProtoType *FT = 0;
if (FD->hasWrittenPrototype())
FT = dyn_cast<FunctionProtoType>(FD->getType()->getAs<FunctionType>());
OS << FD << '(';
if (FT) {
unsigned NumParams = FD->getNumParams();
for (unsigned i = 0; i < NumParams; ++i) {
if (i)
OS << ", ";
std::string Param;
FD->getParamDecl(i)->getType().getAsStringInternal(Param, P);
OS << Param;
}
if (FT->isVariadic()) {
if (NumParams > 0)
OS << ", ";
OS << "...";
}
}
OS << ')';
} else {
OS << cast<NamedDecl>(*I);
}
OS << "::";
}
if (getDeclName())
OS << this;
else
OS << "<anonymous>";
return OS.str();
}
bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
// UsingDirectiveDecl's are not really NamedDecl's, and all have same name.
// We want to keep it, unless it nominates same namespace.
if (getKind() == Decl::UsingDirective) {
return cast<UsingDirectiveDecl>(this)->getNominatedNamespace() ==
cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace();
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
// For function declarations, we keep track of redeclarations.
return FD->getPreviousDeclaration() == OldD;
// For function templates, the underlying function declarations are linked.
if (const FunctionTemplateDecl *FunctionTemplate
= dyn_cast<FunctionTemplateDecl>(this))
if (const FunctionTemplateDecl *OldFunctionTemplate
= dyn_cast<FunctionTemplateDecl>(OldD))
return FunctionTemplate->getTemplatedDecl()
->declarationReplaces(OldFunctionTemplate->getTemplatedDecl());
// For method declarations, we keep track of redeclarations.
if (isa<ObjCMethodDecl>(this))
return false;
if (isa<ObjCInterfaceDecl>(this) && isa<ObjCCompatibleAliasDecl>(OldD))
return true;
if (isa<UsingShadowDecl>(this) && isa<UsingShadowDecl>(OldD))
return cast<UsingShadowDecl>(this)->getTargetDecl() ==
cast<UsingShadowDecl>(OldD)->getTargetDecl();
// For non-function declarations, if the declarations are of the
// same kind then this must be a redeclaration, or semantic analysis
// would not have given us the new declaration.
return this->getKind() == OldD->getKind();
}
bool NamedDecl::hasLinkage() const {
return getLinkage() != NoLinkage;
}
NamedDecl *NamedDecl::getUnderlyingDecl() {
NamedDecl *ND = this;
while (true) {
if (UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(ND))
ND = UD->getTargetDecl();
else if (ObjCCompatibleAliasDecl *AD
= dyn_cast<ObjCCompatibleAliasDecl>(ND))
return AD->getClassInterface();
else
return ND;
}
}
bool NamedDecl::isCXXInstanceMember() const {
assert(isCXXClassMember() &&
"checking whether non-member is instance member");
const NamedDecl *D = this;
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
if (isa<FieldDecl>(D))
return true;
if (isa<CXXMethodDecl>(D))
return cast<CXXMethodDecl>(D)->isInstance();
if (isa<FunctionTemplateDecl>(D))
return cast<CXXMethodDecl>(cast<FunctionTemplateDecl>(D)
->getTemplatedDecl())->isInstance();
return false;
}
//===----------------------------------------------------------------------===//
// DeclaratorDecl Implementation
//===----------------------------------------------------------------------===//
DeclaratorDecl::~DeclaratorDecl() {}
void DeclaratorDecl::Destroy(ASTContext &C) {
if (hasExtInfo())
C.Deallocate(getExtInfo());
ValueDecl::Destroy(C);
}
SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
if (DeclInfo) {
TypeLoc TL = getTypeSourceInfo()->getTypeLoc();
while (true) {
TypeLoc NextTL = TL.getNextTypeLoc();
if (!NextTL)
return TL.getSourceRange().getBegin();
TL = NextTL;
}
}
return SourceLocation();
}
void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
SourceRange QualifierRange) {
if (Qualifier) {
// Make sure the extended decl info is allocated.
if (!hasExtInfo()) {
// Save (non-extended) type source info pointer.
TypeSourceInfo *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
// Allocate external info struct.
DeclInfo = new (getASTContext()) ExtInfo;
// Restore savedTInfo into (extended) decl info.
getExtInfo()->TInfo = savedTInfo;
}
// Set qualifier info.
getExtInfo()->NNS = Qualifier;
getExtInfo()->NNSRange = QualifierRange;
}
else {
// Here Qualifier == 0, i.e., we are removing the qualifier (if any).
assert(QualifierRange.isInvalid());
if (hasExtInfo()) {
// Save type source info pointer.
TypeSourceInfo *savedTInfo = getExtInfo()->TInfo;
// Deallocate the extended decl info.
getASTContext().Deallocate(getExtInfo());
// Restore savedTInfo into (non-extended) decl info.
DeclInfo = savedTInfo;
}
}
}
//===----------------------------------------------------------------------===//
// VarDecl Implementation
//===----------------------------------------------------------------------===//
const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) {
switch (SC) {
case VarDecl::None: break;
case VarDecl::Auto: return "auto"; break;
case VarDecl::Extern: return "extern"; break;
case VarDecl::PrivateExtern: return "__private_extern__"; break;
case VarDecl::Register: return "register"; break;
case VarDecl::Static: return "static"; break;
}
assert(0 && "Invalid storage class");
return 0;
}
VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
StorageClass S, StorageClass SCAsWritten) {
return new (C) VarDecl(Var, DC, L, Id, T, TInfo, S, SCAsWritten);
}
void VarDecl::Destroy(ASTContext& C) {
Expr *Init = getInit();
if (Init) {
Init->Destroy(C);
if (EvaluatedStmt *Eval = this->Init.dyn_cast<EvaluatedStmt *>()) {
Eval->~EvaluatedStmt();
C.Deallocate(Eval);
}
}
this->~VarDecl();
DeclaratorDecl::Destroy(C);
}
VarDecl::~VarDecl() {
}
SourceRange VarDecl::getSourceRange() const {
SourceLocation Start = getTypeSpecStartLoc();
if (Start.isInvalid())
Start = getLocation();
if (getInit())
return SourceRange(Start, getInit()->getLocEnd());
return SourceRange(Start, getLocation());
}
bool VarDecl::isExternC() const {
ASTContext &Context = getASTContext();
if (!Context.getLangOptions().CPlusPlus)
return (getDeclContext()->isTranslationUnit() &&
getStorageClass() != Static) ||
(getDeclContext()->isFunctionOrMethod() && hasExternalStorage());
for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
DC = DC->getParent()) {
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
return getStorageClass() != Static;
break;
}
if (DC->isFunctionOrMethod())
return false;
}
return false;
}
VarDecl *VarDecl::getCanonicalDecl() {
return getFirstDeclaration();
}
VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const {
// C++ [basic.def]p2:
// A declaration is a definition unless [...] it contains the 'extern'
// specifier or a linkage-specification and neither an initializer [...],
// it declares a static data member in a class declaration [...].
// C++ [temp.expl.spec]p15:
// An explicit specialization of a static data member of a template is a
// definition if the declaration includes an initializer; otherwise, it is
// a declaration.
if (isStaticDataMember()) {
if (isOutOfLine() && (hasInit() ||
getTemplateSpecializationKind() != TSK_ExplicitSpecialization))
return Definition;
else
return DeclarationOnly;
}
// C99 6.7p5:
// A definition of an identifier is a declaration for that identifier that
// [...] causes storage to be reserved for that object.
// Note: that applies for all non-file-scope objects.
// C99 6.9.2p1:
// If the declaration of an identifier for an object has file scope and an
// initializer, the declaration is an external definition for the identifier
if (hasInit())
return Definition;
// AST for 'extern "C" int foo;' is annotated with 'extern'.
if (hasExternalStorage())
return DeclarationOnly;
// C99 6.9.2p2:
// A declaration of an object that has file scope without an initializer,
// and without a storage class specifier or the scs 'static', constitutes
// a tentative definition.
// No such thing in C++.
if (!getASTContext().getLangOptions().CPlusPlus && isFileVarDecl())
return TentativeDefinition;
// What's left is (in C, block-scope) declarations without initializers or
// external storage. These are definitions.
return Definition;
}
VarDecl *VarDecl::getActingDefinition() {
DefinitionKind Kind = isThisDeclarationADefinition();
if (Kind != TentativeDefinition)
return 0;
VarDecl *LastTentative = false;
VarDecl *First = getFirstDeclaration();
for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end();
I != E; ++I) {
Kind = (*I)->isThisDeclarationADefinition();
if (Kind == Definition)
return 0;
else if (Kind == TentativeDefinition)
LastTentative = *I;
}
return LastTentative;
}
bool VarDecl::isTentativeDefinitionNow() const {
DefinitionKind Kind = isThisDeclarationADefinition();
if (Kind != TentativeDefinition)
return false;
for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
if ((*I)->isThisDeclarationADefinition() == Definition)
return false;
}
return true;
}
VarDecl *VarDecl::getDefinition() {
VarDecl *First = getFirstDeclaration();
for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end();
I != E; ++I) {
if ((*I)->isThisDeclarationADefinition() == Definition)
return *I;
}
return 0;
}
const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const {
redecl_iterator I = redecls_begin(), E = redecls_end();
while (I != E && !I->getInit())
++I;
if (I != E) {
D = *I;
return I->getInit();
}
return 0;
}
bool VarDecl::isOutOfLine() const {
if (Decl::isOutOfLine())
return true;
if (!isStaticDataMember())
return false;
// If this static data member was instantiated from a static data member of
// a class template, check whether that static data member was defined
// out-of-line.
if (VarDecl *VD = getInstantiatedFromStaticDataMember())
return VD->isOutOfLine();
return false;
}
VarDecl *VarDecl::getOutOfLineDefinition() {
if (!isStaticDataMember())
return 0;
for (VarDecl::redecl_iterator RD = redecls_begin(), RDEnd = redecls_end();
RD != RDEnd; ++RD) {
if (RD->getLexicalDeclContext()->isFileContext())
return *RD;
}
return 0;
}
void VarDecl::setInit(Expr *I) {
if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) {
Eval->~EvaluatedStmt();
getASTContext().Deallocate(Eval);
}
Init = I;
}
VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
return cast<VarDecl>(MSI->getInstantiatedFrom());
return 0;
}
TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const {
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
return MSI->getTemplateSpecializationKind();
return TSK_Undeclared;
}
MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const {
return getASTContext().getInstantiatedFromStaticDataMember(this);
}
void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
SourceLocation PointOfInstantiation) {
MemberSpecializationInfo *MSI = getMemberSpecializationInfo();
assert(MSI && "Not an instantiated static data member?");
MSI->setTemplateSpecializationKind(TSK);
if (TSK != TSK_ExplicitSpecialization &&
PointOfInstantiation.isValid() &&
MSI->getPointOfInstantiation().isInvalid())
MSI->setPointOfInstantiation(PointOfInstantiation);
}
//===----------------------------------------------------------------------===//
// ParmVarDecl Implementation
//===----------------------------------------------------------------------===//
ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo,
StorageClass S, StorageClass SCAsWritten,
Expr *DefArg) {
return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, TInfo,
S, SCAsWritten, DefArg);
}
Expr *ParmVarDecl::getDefaultArg() {
assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!");
assert(!hasUninstantiatedDefaultArg() &&
"Default argument is not yet instantiated!");
Expr *Arg = getInit();
if (CXXExprWithTemporaries *E = dyn_cast_or_null<CXXExprWithTemporaries>(Arg))
return E->getSubExpr();
return Arg;
}
unsigned ParmVarDecl::getNumDefaultArgTemporaries() const {
if (const CXXExprWithTemporaries *E =
dyn_cast<CXXExprWithTemporaries>(getInit()))
return E->getNumTemporaries();
return 0;
}
CXXTemporary *ParmVarDecl::getDefaultArgTemporary(unsigned i) {
assert(getNumDefaultArgTemporaries() &&
"Default arguments does not have any temporaries!");
CXXExprWithTemporaries *E = cast<CXXExprWithTemporaries>(getInit());
return E->getTemporary(i);
}
SourceRange ParmVarDecl::getDefaultArgRange() const {
if (const Expr *E = getInit())
return E->getSourceRange();
if (hasUninstantiatedDefaultArg())
return getUninstantiatedDefaultArg()->getSourceRange();
return SourceRange();
}
//===----------------------------------------------------------------------===//
// FunctionDecl Implementation
//===----------------------------------------------------------------------===//
void FunctionDecl::Destroy(ASTContext& C) {
if (Body && Body.isOffset())
Body.get(C.getExternalSource())->Destroy(C);
for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
(*I)->Destroy(C);
FunctionTemplateSpecializationInfo *FTSInfo
= TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
if (FTSInfo)
C.Deallocate(FTSInfo);
MemberSpecializationInfo *MSInfo
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
if (MSInfo)
C.Deallocate(MSInfo);
C.Deallocate(ParamInfo);
DeclaratorDecl::Destroy(C);
}
void FunctionDecl::getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
bool Qualified) const {
NamedDecl::getNameForDiagnostic(S, Policy, Qualified);
const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs();
if (TemplateArgs)
S += TemplateSpecializationType::PrintTemplateArgumentList(
TemplateArgs->getFlatArgumentList(),
TemplateArgs->flat_size(),
Policy);
}
bool FunctionDecl::isVariadic() const {
if (const FunctionProtoType *FT = getType()->getAs<FunctionProtoType>())
return FT->isVariadic();
return false;
}
Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
if (I->Body) {
Definition = *I;
return I->Body.get(getASTContext().getExternalSource());
}
}
return 0;
}
void FunctionDecl::setBody(Stmt *B) {
Body = B;
if (B)
EndRangeLoc = B->getLocEnd();
}
bool FunctionDecl::isMain() const {
ASTContext &Context = getASTContext();
return !Context.getLangOptions().Freestanding &&
getDeclContext()->getLookupContext()->isTranslationUnit() &&
getIdentifier() && getIdentifier()->isStr("main");
}
bool FunctionDecl::isExternC() const {
ASTContext &Context = getASTContext();
// In C, any non-static, non-overloadable function has external
// linkage.
if (!Context.getLangOptions().CPlusPlus)
return getStorageClass() != Static && !getAttr<OverloadableAttr>();
for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
DC = DC->getParent()) {
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
return getStorageClass() != Static &&
!getAttr<OverloadableAttr>();
break;
}
}
return false;
}
bool FunctionDecl::isGlobal() const {
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this))
return Method->isStatic();
if (getStorageClass() == Static)
return false;
for (const DeclContext *DC = getDeclContext();
DC->isNamespace();
DC = DC->getParent()) {
if (const NamespaceDecl *Namespace = cast<NamespaceDecl>(DC)) {
if (!Namespace->getDeclName())
return false;
break;
}
}
return true;
}
void
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
redeclarable_base::setPreviousDeclaration(PrevDecl);
if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
FunctionTemplateDecl *PrevFunTmpl
= PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0;
assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch");
FunTmpl->setPreviousDeclaration(PrevFunTmpl);
}
}
const FunctionDecl *FunctionDecl::getCanonicalDecl() const {
return getFirstDeclaration();
}
FunctionDecl *FunctionDecl::getCanonicalDecl() {
return getFirstDeclaration();
}
Implicitly declare certain C library functions (malloc, strcpy, memmove, etc.) when we perform name lookup on them. This ensures that we produce the correct signature for these functions, which has two practical impacts: 1) When we're supporting the "implicit function declaration" feature of C99, these functions will be implicitly declared with the right signature rather than as a function returning "int" with no prototype. See PR3541 for the reason why this is important (hint: GCC always predeclares these functions). 2) If users attempt to redeclare one of these library functions with an incompatible signature, we produce a hard error. This patch does a little bit of work to give reasonable error messages. For example, when we hit case #1 we complain that we're implicitly declaring this function with a specific signature, and then we give a note that asks the user to include the appropriate header (e.g., "please include <stdlib.h> or explicitly declare 'malloc'"). In case #2, we show the type of the implicit builtin that was incorrectly declared, so the user can see the problem. We could do better here: for example, when displaying this latter error message we say something like: 'strcpy' was implicitly declared here with type 'char *(char *, char const *)' but we should really print out a fake code line showing the declaration, like this: 'strcpy' was implicitly declared here as: char *strcpy(char *, char const *) This would also be good for printing built-in candidates with C++ operator overloading. The set of C library functions supported by this patch includes all functions from the C99 specification's <stdlib.h> and <string.h> that (a) are predefined by GCC and (b) have signatures that could cause codegen issues if they are treated as functions with no prototype returning and int. Future work could extend this set of functions to other C library functions that we know about. llvm-svn: 64504
2009-02-13 23:20:09 +00:00
/// \brief Returns a value indicating whether this function
/// corresponds to a builtin function.
///
/// The function corresponds to a built-in function if it is
/// declared at translation scope or within an extern "C" block and
/// its name matches with the name of a builtin. The returned value
/// will be 0 for functions that do not correspond to a builtin, a
/// value of type \c Builtin::ID if in the target-independent range
Implicitly declare certain C library functions (malloc, strcpy, memmove, etc.) when we perform name lookup on them. This ensures that we produce the correct signature for these functions, which has two practical impacts: 1) When we're supporting the "implicit function declaration" feature of C99, these functions will be implicitly declared with the right signature rather than as a function returning "int" with no prototype. See PR3541 for the reason why this is important (hint: GCC always predeclares these functions). 2) If users attempt to redeclare one of these library functions with an incompatible signature, we produce a hard error. This patch does a little bit of work to give reasonable error messages. For example, when we hit case #1 we complain that we're implicitly declaring this function with a specific signature, and then we give a note that asks the user to include the appropriate header (e.g., "please include <stdlib.h> or explicitly declare 'malloc'"). In case #2, we show the type of the implicit builtin that was incorrectly declared, so the user can see the problem. We could do better here: for example, when displaying this latter error message we say something like: 'strcpy' was implicitly declared here with type 'char *(char *, char const *)' but we should really print out a fake code line showing the declaration, like this: 'strcpy' was implicitly declared here as: char *strcpy(char *, char const *) This would also be good for printing built-in candidates with C++ operator overloading. The set of C library functions supported by this patch includes all functions from the C99 specification's <stdlib.h> and <string.h> that (a) are predefined by GCC and (b) have signatures that could cause codegen issues if they are treated as functions with no prototype returning and int. Future work could extend this set of functions to other C library functions that we know about. llvm-svn: 64504
2009-02-13 23:20:09 +00:00
/// \c [1,Builtin::First), or a target-specific builtin value.
unsigned FunctionDecl::getBuiltinID() const {
ASTContext &Context = getASTContext();
if (!getIdentifier() || !getIdentifier()->getBuiltinID())
return 0;
unsigned BuiltinID = getIdentifier()->getBuiltinID();
if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return BuiltinID;
// This function has the name of a known C library
// function. Determine whether it actually refers to the C library
// function or whether it just has the same name.
// If this is a static function, it's not a builtin.
if (getStorageClass() == Static)
return 0;
// If this function is at translation-unit scope and we're not in
// C++, it refers to the C library function.
if (!Context.getLangOptions().CPlusPlus &&
getDeclContext()->isTranslationUnit())
return BuiltinID;
// If the function is in an extern "C" linkage specification and is
// not marked "overloadable", it's the real function.
if (isa<LinkageSpecDecl>(getDeclContext()) &&
cast<LinkageSpecDecl>(getDeclContext())->getLanguage()
== LinkageSpecDecl::lang_c &&
!getAttr<OverloadableAttr>())
return BuiltinID;
// Not a builtin
Implicitly declare certain C library functions (malloc, strcpy, memmove, etc.) when we perform name lookup on them. This ensures that we produce the correct signature for these functions, which has two practical impacts: 1) When we're supporting the "implicit function declaration" feature of C99, these functions will be implicitly declared with the right signature rather than as a function returning "int" with no prototype. See PR3541 for the reason why this is important (hint: GCC always predeclares these functions). 2) If users attempt to redeclare one of these library functions with an incompatible signature, we produce a hard error. This patch does a little bit of work to give reasonable error messages. For example, when we hit case #1 we complain that we're implicitly declaring this function with a specific signature, and then we give a note that asks the user to include the appropriate header (e.g., "please include <stdlib.h> or explicitly declare 'malloc'"). In case #2, we show the type of the implicit builtin that was incorrectly declared, so the user can see the problem. We could do better here: for example, when displaying this latter error message we say something like: 'strcpy' was implicitly declared here with type 'char *(char *, char const *)' but we should really print out a fake code line showing the declaration, like this: 'strcpy' was implicitly declared here as: char *strcpy(char *, char const *) This would also be good for printing built-in candidates with C++ operator overloading. The set of C library functions supported by this patch includes all functions from the C99 specification's <stdlib.h> and <string.h> that (a) are predefined by GCC and (b) have signatures that could cause codegen issues if they are treated as functions with no prototype returning and int. Future work could extend this set of functions to other C library functions that we know about. llvm-svn: 64504
2009-02-13 23:20:09 +00:00
return 0;
}
/// getNumParams - Return the number of parameters this function must have
/// based on its FunctionType. This is the length of the PararmInfo array
/// after it has been created.
unsigned FunctionDecl::getNumParams() const {
const FunctionType *FT = getType()->getAs<FunctionType>();
if (isa<FunctionNoProtoType>(FT))
return 0;
return cast<FunctionProtoType>(FT)->getNumArgs();
}
void FunctionDecl::setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) {
assert(ParamInfo == 0 && "Already has param info!");
assert(NumParams == getNumParams() && "Parameter count mismatch!");
// Zero params -> null pointer.
if (NumParams) {
void *Mem = getASTContext().Allocate(sizeof(ParmVarDecl*)*NumParams);
ParamInfo = new (Mem) ParmVarDecl*[NumParams];
memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
2009-06-23 00:42:00 +00:00
// Update source range. The check below allows us to set EndRangeLoc before
// setting the parameters.
if (EndRangeLoc.isInvalid() || EndRangeLoc == getLocation())
EndRangeLoc = NewParamInfo[NumParams-1]->getLocEnd();
}
}
/// getMinRequiredArguments - Returns the minimum number of arguments
/// needed to call this function. This may be fewer than the number of
/// function parameters, if some of the parameters have default
/// arguments (in C++).
unsigned FunctionDecl::getMinRequiredArguments() const {
unsigned NumRequiredArgs = getNumParams();
while (NumRequiredArgs > 0
&& getParamDecl(NumRequiredArgs-1)->hasDefaultArg())
--NumRequiredArgs;
return NumRequiredArgs;
}
bool FunctionDecl::isInlined() const {
// FIXME: This is not enough. Consider:
//
// inline void f();
// void f() { }
//
// f is inlined, but does not have inline specified.
// To fix this we should add an 'inline' flag to FunctionDecl.
if (isInlineSpecified())
return true;
if (isa<CXXMethodDecl>(this)) {
if (!isOutOfLine() || getCanonicalDecl()->isInlineSpecified())
return true;
}
switch (getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
return false;
case TSK_ImplicitInstantiation:
case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition:
// Handle below.
break;
}
const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
Stmt *Pattern = 0;
if (PatternDecl)
Pattern = PatternDecl->getBody(PatternDecl);
if (Pattern && PatternDecl)
return PatternDecl->isInlined();
return false;
}
/// \brief For an inline function definition in C or C++, determine whether the
/// definition will be externally visible.
///
/// Inline function definitions are always available for inlining optimizations.
/// However, depending on the language dialect, declaration specifiers, and
/// attributes, the definition of an inline function may or may not be
/// "externally" visible to other translation units in the program.
///
/// In C99, inline definitions are not externally visible by default. However,
2010-01-06 02:05:39 +00:00
/// if even one of the global-scope declarations is marked "extern inline", the
/// inline definition becomes externally visible (C99 6.7.4p6).
///
/// In GNU89 mode, or if the gnu_inline attribute is attached to the function
/// definition, we use the GNU semantics for inline, which are nearly the
/// opposite of C99 semantics. In particular, "inline" by itself will create
/// an externally visible symbol, but "extern inline" will not create an
/// externally visible symbol.
bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
assert(isThisDeclarationADefinition() && "Must have the function definition");
assert(isInlined() && "Function must be inline");
ASTContext &Context = getASTContext();
if (!Context.getLangOptions().C99 || hasAttr<GNUInlineAttr>()) {
// GNU inline semantics. Based on a number of examples, we came up with the
// following heuristic: if the "inline" keyword is present on a
// declaration of the function but "extern" is not present on that
// declaration, then the symbol is externally visible. Otherwise, the GNU
// "extern inline" semantics applies and the symbol is not externally
// visible.
for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end();
Redecl != RedeclEnd;
++Redecl) {
if (Redecl->isInlineSpecified() && Redecl->getStorageClass() != Extern)
return true;
}
// GNU "extern inline" semantics; no externally visible symbol.
return false;
}
// C99 6.7.4p6:
// [...] If all of the file scope declarations for a function in a
// translation unit include the inline function specifier without extern,
// then the definition in that translation unit is an inline definition.
for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end();
Redecl != RedeclEnd;
++Redecl) {
// Only consider file-scope declarations in this test.
if (!Redecl->getLexicalDeclContext()->isTranslationUnit())
continue;
if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == Extern)
return true; // Not an inline definition
}
// C99 6.7.4p6:
// An inline definition does not provide an external definition for the
// function, and does not forbid an external definition in another
// translation unit.
return false;
}
/// getOverloadedOperator - Which C++ overloaded operator this
/// function represents, if any.
OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
return getDeclName().getCXXOverloadedOperator();
else
return OO_None;
}
/// getLiteralIdentifier - The literal suffix identifier this function
/// represents, if any.
const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const {
if (getDeclName().getNameKind() == DeclarationName::CXXLiteralOperatorName)
return getDeclName().getCXXLiteralIdentifier();
else
return 0;
}
FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
if (MemberSpecializationInfo *Info = getMemberSpecializationInfo())
return cast<FunctionDecl>(Info->getInstantiatedFrom());
return 0;
}
MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const {
return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
}
void
FunctionDecl::setInstantiationOfMemberFunction(FunctionDecl *FD,
TemplateSpecializationKind TSK) {
assert(TemplateOrSpecialization.isNull() &&
"Member function is already a specialization");
MemberSpecializationInfo *Info
= new (getASTContext()) MemberSpecializationInfo(FD, TSK);
TemplateOrSpecialization = Info;
}
bool FunctionDecl::isImplicitlyInstantiable() const {
// If the function is invalid, it can't be implicitly instantiated.
if (isInvalidDecl())
return false;
switch (getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
case TSK_ExplicitInstantiationDefinition:
return false;
case TSK_ImplicitInstantiation:
return true;
case TSK_ExplicitInstantiationDeclaration:
// Handled below.
break;
}
// Find the actual template from which we will instantiate.
const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
Stmt *Pattern = 0;
if (PatternDecl)
Pattern = PatternDecl->getBody(PatternDecl);
// C++0x [temp.explicit]p9:
// Except for inline functions, other explicit instantiation declarations
// have the effect of suppressing the implicit instantiation of the entity
// to which they refer.
if (!Pattern || !PatternDecl)
return true;
return PatternDecl->isInlined();
}
FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
while (Primary->getInstantiatedFromMemberTemplate()) {
// If we have hit a point where the user provided a specialization of
// this template, we're done looking.
if (Primary->isMemberSpecialization())
break;
Primary = Primary->getInstantiatedFromMemberTemplate();
}
return Primary->getTemplatedDecl();
}
return getInstantiatedFromMemberFunction();
}
FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
if (FunctionTemplateSpecializationInfo *Info
= TemplateOrSpecialization
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
return Info->Template.getPointer();
}
return 0;
}
const TemplateArgumentList *
FunctionDecl::getTemplateSpecializationArgs() const {
if (FunctionTemplateSpecializationInfo *Info
= TemplateOrSpecialization
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
return Info->TemplateArguments;
}
return 0;
}
void
FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
const TemplateArgumentList *TemplateArgs,
void *InsertPos,
TemplateSpecializationKind TSK) {
assert(TSK != TSK_Undeclared &&
"Must specify the type of function template specialization");
FunctionTemplateSpecializationInfo *Info
= TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
if (!Info)
Info = new (getASTContext()) FunctionTemplateSpecializationInfo;
Info->Function = this;
Info->Template.setPointer(Template);
Info->Template.setInt(TSK - 1);
Info->TemplateArguments = TemplateArgs;
TemplateOrSpecialization = Info;
// Insert this function template specialization into the set of known
// function template specializations.
if (InsertPos)
Template->getSpecializations().InsertNode(Info, InsertPos);
else {
// Try to insert the new node. If there is an existing node, remove it
// first.
FunctionTemplateSpecializationInfo *Existing
= Template->getSpecializations().GetOrInsertNode(Info);
if (Existing) {
Template->getSpecializations().RemoveNode(Existing);
Template->getSpecializations().GetOrInsertNode(Info);
}
}
}
void
FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context,
const UnresolvedSetImpl &Templates,
const TemplateArgumentListInfo &TemplateArgs) {
assert(TemplateOrSpecialization.isNull());
size_t Size = sizeof(DependentFunctionTemplateSpecializationInfo);
Size += Templates.size() * sizeof(FunctionTemplateDecl*);
Size += TemplateArgs.size() * sizeof(TemplateArgumentLoc);
void *Buffer = Context.Allocate(Size);
DependentFunctionTemplateSpecializationInfo *Info =
new (Buffer) DependentFunctionTemplateSpecializationInfo(Templates,
TemplateArgs);
TemplateOrSpecialization = Info;
}
DependentFunctionTemplateSpecializationInfo::
DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts,
const TemplateArgumentListInfo &TArgs)
: AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) {
d.NumTemplates = Ts.size();
d.NumArgs = TArgs.size();
FunctionTemplateDecl **TsArray =
const_cast<FunctionTemplateDecl**>(getTemplates());
for (unsigned I = 0, E = Ts.size(); I != E; ++I)
TsArray[I] = cast<FunctionTemplateDecl>(Ts[I]->getUnderlyingDecl());
TemplateArgumentLoc *ArgsArray =
const_cast<TemplateArgumentLoc*>(getTemplateArgs());
for (unsigned I = 0, E = TArgs.size(); I != E; ++I)
new (&ArgsArray[I]) TemplateArgumentLoc(TArgs[I]);
}
TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
// For a function template specialization, query the specialization
// information object.
FunctionTemplateSpecializationInfo *FTSInfo
= TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
if (FTSInfo)
return FTSInfo->getTemplateSpecializationKind();
MemberSpecializationInfo *MSInfo
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
if (MSInfo)
return MSInfo->getTemplateSpecializationKind();
return TSK_Undeclared;
}
void
FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
SourceLocation PointOfInstantiation) {
if (FunctionTemplateSpecializationInfo *FTSInfo
= TemplateOrSpecialization.dyn_cast<
FunctionTemplateSpecializationInfo*>()) {
FTSInfo->setTemplateSpecializationKind(TSK);
if (TSK != TSK_ExplicitSpecialization &&
PointOfInstantiation.isValid() &&
FTSInfo->getPointOfInstantiation().isInvalid())
FTSInfo->setPointOfInstantiation(PointOfInstantiation);
} else if (MemberSpecializationInfo *MSInfo
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) {
MSInfo->setTemplateSpecializationKind(TSK);
if (TSK != TSK_ExplicitSpecialization &&
PointOfInstantiation.isValid() &&
MSInfo->getPointOfInstantiation().isInvalid())
MSInfo->setPointOfInstantiation(PointOfInstantiation);
} else
assert(false && "Function cannot have a template specialization kind");
}
SourceLocation FunctionDecl::getPointOfInstantiation() const {
if (FunctionTemplateSpecializationInfo *FTSInfo
= TemplateOrSpecialization.dyn_cast<
FunctionTemplateSpecializationInfo*>())
return FTSInfo->getPointOfInstantiation();
else if (MemberSpecializationInfo *MSInfo
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>())
return MSInfo->getPointOfInstantiation();
return SourceLocation();
}
bool FunctionDecl::isOutOfLine() const {
if (Decl::isOutOfLine())
return true;
// If this function was instantiated from a member function of a
// class template, check whether that member function was defined out-of-line.
if (FunctionDecl *FD = getInstantiatedFromMemberFunction()) {
const FunctionDecl *Definition;
if (FD->getBody(Definition))
return Definition->isOutOfLine();
}
// If this function was instantiated from a function template,
// check whether that function template was defined out-of-line.
if (FunctionTemplateDecl *FunTmpl = getPrimaryTemplate()) {
const FunctionDecl *Definition;
if (FunTmpl->getTemplatedDecl()->getBody(Definition))
return Definition->isOutOfLine();
}
return false;
}
//===----------------------------------------------------------------------===//
// FieldDecl Implementation
//===----------------------------------------------------------------------===//
FieldDecl *FieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, Expr *BW, bool Mutable) {
return new (C) FieldDecl(Decl::Field, DC, L, Id, T, TInfo, BW, Mutable);
}
bool FieldDecl::isAnonymousStructOrUnion() const {
if (!isImplicit() || getDeclName())
return false;
if (const RecordType *Record = getType()->getAs<RecordType>())
return Record->getDecl()->isAnonymousStructOrUnion();
return false;
}
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it. This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet). The motivation of this patch is as follows: - Capture more source information, necessary for refactoring/rewriting clients. - Pave the way to resolve ownership issues with RecordDecls with the forthcoming addition of DeclGroups. Current caveats: - Until DeclGroups are in place, we will leak RecordDecls not explicitly referenced by the AST. For example: typedef struct { ... } x; The RecordDecl for the struct will be leaked because the TypedefDecl doesn't refer to it. This will be solved with DeclGroups. - This patch also (temporarily) breaks CodeGen. More below. High-level changes: - As before, TagType still refers to a TagDecl, but it doesn't own it. When a struct/union/class is first referenced, a RecordType and RecordDecl are created for it, and the RecordType refers to that RecordDecl. Later, if a new RecordDecl is created, the pointer to a RecordDecl in RecordType is updated to point to the RecordDecl that defines the struct/union/class. - TagDecl and RecordDecl now how a method 'getDefinition()' to return the TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular enum/struct/class/union. This is useful from going from a RecordDecl* that defines a forward declaration to the RecordDecl* that provides the actual definition. Note that this also works for EnumDecls, except that in this case there is no distinction between forward declarations and definitions (yet). - Clients should no longer assume that 'isDefinition()' returns true from a RecordDecl if the corresponding struct/union/class has been defined. isDefinition() only returns true if a particular RecordDecl is the defining Decl. Use 'getDefinition()' instead to determine if a struct has been defined. - The main changes to Sema happen in ActOnTag. To make the changes more incremental, I split off the processing of enums and structs et al into two code paths. Enums use the original code path (which is in ActOnTag) and structs use the ActOnTagStruct. Eventually the two code paths will be merged, but the idea was to preserve the original logic both for comparison and not to change the logic for both enums and structs all at once. - There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls that correspond to the same type simply have a pointer to that type. If we need to figure out what are all the RecordDecls for a given type we can build a backmap. - The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the changes to RecordDecl. For some reason 'svn' marks the entire file as changed. Why is CodeGen broken: - Codegen assumes that there is an equivalence between RecordDecl* and RecordType*. This was true before because we only created one RecordDecl* for a given RecordType*, but it is no longer true. I believe this shouldn't be too hard to change, but the patch was big enough as it is. I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C). llvm-svn: 55839
2008-09-05 17:16:31 +00:00
//===----------------------------------------------------------------------===//
// TagDecl Implementation
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it. This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet). The motivation of this patch is as follows: - Capture more source information, necessary for refactoring/rewriting clients. - Pave the way to resolve ownership issues with RecordDecls with the forthcoming addition of DeclGroups. Current caveats: - Until DeclGroups are in place, we will leak RecordDecls not explicitly referenced by the AST. For example: typedef struct { ... } x; The RecordDecl for the struct will be leaked because the TypedefDecl doesn't refer to it. This will be solved with DeclGroups. - This patch also (temporarily) breaks CodeGen. More below. High-level changes: - As before, TagType still refers to a TagDecl, but it doesn't own it. When a struct/union/class is first referenced, a RecordType and RecordDecl are created for it, and the RecordType refers to that RecordDecl. Later, if a new RecordDecl is created, the pointer to a RecordDecl in RecordType is updated to point to the RecordDecl that defines the struct/union/class. - TagDecl and RecordDecl now how a method 'getDefinition()' to return the TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular enum/struct/class/union. This is useful from going from a RecordDecl* that defines a forward declaration to the RecordDecl* that provides the actual definition. Note that this also works for EnumDecls, except that in this case there is no distinction between forward declarations and definitions (yet). - Clients should no longer assume that 'isDefinition()' returns true from a RecordDecl if the corresponding struct/union/class has been defined. isDefinition() only returns true if a particular RecordDecl is the defining Decl. Use 'getDefinition()' instead to determine if a struct has been defined. - The main changes to Sema happen in ActOnTag. To make the changes more incremental, I split off the processing of enums and structs et al into two code paths. Enums use the original code path (which is in ActOnTag) and structs use the ActOnTagStruct. Eventually the two code paths will be merged, but the idea was to preserve the original logic both for comparison and not to change the logic for both enums and structs all at once. - There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls that correspond to the same type simply have a pointer to that type. If we need to figure out what are all the RecordDecls for a given type we can build a backmap. - The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the changes to RecordDecl. For some reason 'svn' marks the entire file as changed. Why is CodeGen broken: - Codegen assumes that there is an equivalence between RecordDecl* and RecordType*. This was true before because we only created one RecordDecl* for a given RecordType*, but it is no longer true. I believe this shouldn't be too hard to change, but the patch was big enough as it is. I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C). llvm-svn: 55839
2008-09-05 17:16:31 +00:00
//===----------------------------------------------------------------------===//
void TagDecl::Destroy(ASTContext &C) {
if (hasExtInfo())
C.Deallocate(getExtInfo());
TypeDecl::Destroy(C);
}
SourceRange TagDecl::getSourceRange() const {
SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation();
return SourceRange(TagKeywordLoc, E);
}
TagDecl* TagDecl::getCanonicalDecl() {
return getFirstDeclaration();
}
void TagDecl::startDefinition() {
if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) {
TagT->decl.setPointer(this);
TagT->decl.setInt(1);
} else if (InjectedClassNameType *Injected
= const_cast<InjectedClassNameType *>(
TypeForDecl->getAs<InjectedClassNameType>())) {
Injected->Decl = cast<CXXRecordDecl>(this);
}
if (isa<CXXRecordDecl>(this)) {
CXXRecordDecl *D = cast<CXXRecordDecl>(this);
struct CXXRecordDecl::DefinitionData *Data =
new (getASTContext()) struct CXXRecordDecl::DefinitionData(D);
for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I)
cast<CXXRecordDecl>(*I)->DefinitionData = Data;
}
}
void TagDecl::completeDefinition() {
assert((!isa<CXXRecordDecl>(this) ||
cast<CXXRecordDecl>(this)->hasDefinition()) &&
"definition completed but not started");
IsDefinition = true;
if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) {
assert(TagT->decl.getPointer() == this &&
"Attempt to redefine a tag definition?");
TagT->decl.setInt(0);
} else if (InjectedClassNameType *Injected
= const_cast<InjectedClassNameType *>(
TypeForDecl->getAs<InjectedClassNameType>())) {
assert(Injected->Decl == this &&
"Attempt to redefine a class template definition?");
(void)Injected;
}
}
TagDecl* TagDecl::getDefinition() const {
if (isDefinition())
return const_cast<TagDecl *>(this);
for (redecl_iterator R = redecls_begin(), REnd = redecls_end();
R != REnd; ++R)
if (R->isDefinition())
return *R;
return 0;
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it. This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet). The motivation of this patch is as follows: - Capture more source information, necessary for refactoring/rewriting clients. - Pave the way to resolve ownership issues with RecordDecls with the forthcoming addition of DeclGroups. Current caveats: - Until DeclGroups are in place, we will leak RecordDecls not explicitly referenced by the AST. For example: typedef struct { ... } x; The RecordDecl for the struct will be leaked because the TypedefDecl doesn't refer to it. This will be solved with DeclGroups. - This patch also (temporarily) breaks CodeGen. More below. High-level changes: - As before, TagType still refers to a TagDecl, but it doesn't own it. When a struct/union/class is first referenced, a RecordType and RecordDecl are created for it, and the RecordType refers to that RecordDecl. Later, if a new RecordDecl is created, the pointer to a RecordDecl in RecordType is updated to point to the RecordDecl that defines the struct/union/class. - TagDecl and RecordDecl now how a method 'getDefinition()' to return the TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular enum/struct/class/union. This is useful from going from a RecordDecl* that defines a forward declaration to the RecordDecl* that provides the actual definition. Note that this also works for EnumDecls, except that in this case there is no distinction between forward declarations and definitions (yet). - Clients should no longer assume that 'isDefinition()' returns true from a RecordDecl if the corresponding struct/union/class has been defined. isDefinition() only returns true if a particular RecordDecl is the defining Decl. Use 'getDefinition()' instead to determine if a struct has been defined. - The main changes to Sema happen in ActOnTag. To make the changes more incremental, I split off the processing of enums and structs et al into two code paths. Enums use the original code path (which is in ActOnTag) and structs use the ActOnTagStruct. Eventually the two code paths will be merged, but the idea was to preserve the original logic both for comparison and not to change the logic for both enums and structs all at once. - There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls that correspond to the same type simply have a pointer to that type. If we need to figure out what are all the RecordDecls for a given type we can build a backmap. - The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the changes to RecordDecl. For some reason 'svn' marks the entire file as changed. Why is CodeGen broken: - Codegen assumes that there is an equivalence between RecordDecl* and RecordType*. This was true before because we only created one RecordDecl* for a given RecordType*, but it is no longer true. I believe this shouldn't be too hard to change, but the patch was big enough as it is. I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C). llvm-svn: 55839
2008-09-05 17:16:31 +00:00
}
void TagDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
SourceRange QualifierRange) {
if (Qualifier) {
// Make sure the extended qualifier info is allocated.
if (!hasExtInfo())
TypedefDeclOrQualifier = new (getASTContext()) ExtInfo;
// Set qualifier info.
getExtInfo()->NNS = Qualifier;
getExtInfo()->NNSRange = QualifierRange;
}
else {
// Here Qualifier == 0, i.e., we are removing the qualifier (if any).
assert(QualifierRange.isInvalid());
if (hasExtInfo()) {
getASTContext().Deallocate(getExtInfo());
TypedefDeclOrQualifier = (TypedefDecl*) 0;
}
}
}
//===----------------------------------------------------------------------===//
// EnumDecl Implementation
//===----------------------------------------------------------------------===//
EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, SourceLocation TKL,
EnumDecl *PrevDecl) {
EnumDecl *Enum = new (C) EnumDecl(DC, L, Id, PrevDecl, TKL);
C.getTypeDeclType(Enum, PrevDecl);
return Enum;
}
void EnumDecl::Destroy(ASTContext& C) {
TagDecl::Destroy(C);
}
void EnumDecl::completeDefinition(QualType NewType,
QualType NewPromotionType,
unsigned NumPositiveBits,
unsigned NumNegativeBits) {
assert(!isDefinition() && "Cannot redefine enums!");
IntegerType = NewType;
PromotionType = NewPromotionType;
setNumPositiveBits(NumPositiveBits);
setNumNegativeBits(NumNegativeBits);
TagDecl::completeDefinition();
}
//===----------------------------------------------------------------------===//
// RecordDecl Implementation
//===----------------------------------------------------------------------===//
RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, RecordDecl *PrevDecl,
SourceLocation TKL)
: TagDecl(DK, TK, DC, L, Id, PrevDecl, TKL) {
HasFlexibleArrayMember = false;
AnonymousStructOrUnion = false;
HasObjectMember = false;
assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
}
RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it. This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet). The motivation of this patch is as follows: - Capture more source information, necessary for refactoring/rewriting clients. - Pave the way to resolve ownership issues with RecordDecls with the forthcoming addition of DeclGroups. Current caveats: - Until DeclGroups are in place, we will leak RecordDecls not explicitly referenced by the AST. For example: typedef struct { ... } x; The RecordDecl for the struct will be leaked because the TypedefDecl doesn't refer to it. This will be solved with DeclGroups. - This patch also (temporarily) breaks CodeGen. More below. High-level changes: - As before, TagType still refers to a TagDecl, but it doesn't own it. When a struct/union/class is first referenced, a RecordType and RecordDecl are created for it, and the RecordType refers to that RecordDecl. Later, if a new RecordDecl is created, the pointer to a RecordDecl in RecordType is updated to point to the RecordDecl that defines the struct/union/class. - TagDecl and RecordDecl now how a method 'getDefinition()' to return the TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular enum/struct/class/union. This is useful from going from a RecordDecl* that defines a forward declaration to the RecordDecl* that provides the actual definition. Note that this also works for EnumDecls, except that in this case there is no distinction between forward declarations and definitions (yet). - Clients should no longer assume that 'isDefinition()' returns true from a RecordDecl if the corresponding struct/union/class has been defined. isDefinition() only returns true if a particular RecordDecl is the defining Decl. Use 'getDefinition()' instead to determine if a struct has been defined. - The main changes to Sema happen in ActOnTag. To make the changes more incremental, I split off the processing of enums and structs et al into two code paths. Enums use the original code path (which is in ActOnTag) and structs use the ActOnTagStruct. Eventually the two code paths will be merged, but the idea was to preserve the original logic both for comparison and not to change the logic for both enums and structs all at once. - There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls that correspond to the same type simply have a pointer to that type. If we need to figure out what are all the RecordDecls for a given type we can build a backmap. - The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the changes to RecordDecl. For some reason 'svn' marks the entire file as changed. Why is CodeGen broken: - Codegen assumes that there is an equivalence between RecordDecl* and RecordType*. This was true before because we only created one RecordDecl* for a given RecordType*, but it is no longer true. I believe this shouldn't be too hard to change, but the patch was big enough as it is. I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C). llvm-svn: 55839
2008-09-05 17:16:31 +00:00
SourceLocation L, IdentifierInfo *Id,
SourceLocation TKL, RecordDecl* PrevDecl) {
RecordDecl* R = new (C) RecordDecl(Record, TK, DC, L, Id, PrevDecl, TKL);
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it. This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet). The motivation of this patch is as follows: - Capture more source information, necessary for refactoring/rewriting clients. - Pave the way to resolve ownership issues with RecordDecls with the forthcoming addition of DeclGroups. Current caveats: - Until DeclGroups are in place, we will leak RecordDecls not explicitly referenced by the AST. For example: typedef struct { ... } x; The RecordDecl for the struct will be leaked because the TypedefDecl doesn't refer to it. This will be solved with DeclGroups. - This patch also (temporarily) breaks CodeGen. More below. High-level changes: - As before, TagType still refers to a TagDecl, but it doesn't own it. When a struct/union/class is first referenced, a RecordType and RecordDecl are created for it, and the RecordType refers to that RecordDecl. Later, if a new RecordDecl is created, the pointer to a RecordDecl in RecordType is updated to point to the RecordDecl that defines the struct/union/class. - TagDecl and RecordDecl now how a method 'getDefinition()' to return the TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular enum/struct/class/union. This is useful from going from a RecordDecl* that defines a forward declaration to the RecordDecl* that provides the actual definition. Note that this also works for EnumDecls, except that in this case there is no distinction between forward declarations and definitions (yet). - Clients should no longer assume that 'isDefinition()' returns true from a RecordDecl if the corresponding struct/union/class has been defined. isDefinition() only returns true if a particular RecordDecl is the defining Decl. Use 'getDefinition()' instead to determine if a struct has been defined. - The main changes to Sema happen in ActOnTag. To make the changes more incremental, I split off the processing of enums and structs et al into two code paths. Enums use the original code path (which is in ActOnTag) and structs use the ActOnTagStruct. Eventually the two code paths will be merged, but the idea was to preserve the original logic both for comparison and not to change the logic for both enums and structs all at once. - There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls that correspond to the same type simply have a pointer to that type. If we need to figure out what are all the RecordDecls for a given type we can build a backmap. - The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the changes to RecordDecl. For some reason 'svn' marks the entire file as changed. Why is CodeGen broken: - Codegen assumes that there is an equivalence between RecordDecl* and RecordType*. This was true before because we only created one RecordDecl* for a given RecordType*, but it is no longer true. I believe this shouldn't be too hard to change, but the patch was big enough as it is. I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C). llvm-svn: 55839
2008-09-05 17:16:31 +00:00
C.getTypeDeclType(R, PrevDecl);
return R;
}
RecordDecl::~RecordDecl() {
}
void RecordDecl::Destroy(ASTContext& C) {
TagDecl::Destroy(C);
}
bool RecordDecl::isInjectedClassName() const {
return isImplicit() && getDeclName() && getDeclContext()->isRecord() &&
cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName();
}
/// completeDefinition - Notes that the definition of this type is now
/// complete.
void RecordDecl::completeDefinition() {
assert(!isDefinition() && "Cannot redefine record!");
TagDecl::completeDefinition();
}
//===----------------------------------------------------------------------===//
// BlockDecl Implementation
//===----------------------------------------------------------------------===//
BlockDecl::~BlockDecl() {
}
void BlockDecl::Destroy(ASTContext& C) {
if (Body)
Body->Destroy(C);
for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
(*I)->Destroy(C);
C.Deallocate(ParamInfo);
Decl::Destroy(C);
}
void BlockDecl::setParams(ParmVarDecl **NewParamInfo,
unsigned NParms) {
assert(ParamInfo == 0 && "Already has param info!");
// Zero params -> null pointer.
if (NParms) {
NumParams = NParms;
void *Mem = getASTContext().Allocate(sizeof(ParmVarDecl*)*NumParams);
ParamInfo = new (Mem) ParmVarDecl*[NumParams];
memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
}
}
unsigned BlockDecl::getNumParams() const {
return NumParams;
}
//===----------------------------------------------------------------------===//
// Other Decl Allocation/Deallocation Method Implementations
//===----------------------------------------------------------------------===//
TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
return new (C) TranslationUnitDecl(C);
}
NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id) {
return new (C) NamespaceDecl(DC, L, Id);
}
void NamespaceDecl::Destroy(ASTContext& C) {
// NamespaceDecl uses "NextDeclarator" to chain namespace declarations
// together. They are all top-level Decls.
this->~NamespaceDecl();
Decl::Destroy(C);
}
ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id, QualType T) {
return new (C) ImplicitParamDecl(ImplicitParam, DC, L, Id, T);
}
FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
DeclarationName N, QualType T,
TypeSourceInfo *TInfo,
StorageClass S, StorageClass SCAsWritten,
bool isInline, bool hasWrittenPrototype) {
FunctionDecl *New = new (C) FunctionDecl(Function, DC, L, N, T, TInfo,
S, SCAsWritten, isInline);
New->HasWrittenPrototype = hasWrittenPrototype;
return New;
}
BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
return new (C) BlockDecl(DC, L);
}
EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
SourceLocation L,
IdentifierInfo *Id, QualType T,
Expr *E, const llvm::APSInt &V) {
return new (C) EnumConstantDecl(CD, L, Id, T, E, V);
}
void EnumConstantDecl::Destroy(ASTContext& C) {
if (Init) Init->Destroy(C);
ValueDecl::Destroy(C);
}
TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
TypeSourceInfo *TInfo) {
return new (C) TypedefDecl(DC, L, Id, TInfo);
}
// Anchor TypedefDecl's vtable here.
TypedefDecl::~TypedefDecl() {}
FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
StringLiteral *Str) {
return new (C) FileScopeAsmDecl(DC, L, Str);
}