2017-11-13 23:01:27 +00:00
|
|
|
//===- Decl.cpp - Declaration AST Node Implementation ---------------------===//
|
2006-10-15 22:34:45 +00:00
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2006-10-15 22:34:45 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2008-06-04 13:04:04 +00:00
|
|
|
// This file implements the Decl subclasses.
|
2006-10-15 22:34:45 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/AST/Decl.h"
|
2017-08-09 04:02:49 +00:00
|
|
|
#include "Linkage.h"
|
2008-03-15 06:12:44 +00:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2018-12-14 03:35:10 +00:00
|
|
|
#include "clang/AST/ASTDiagnostic.h"
|
2014-04-03 16:32:21 +00:00
|
|
|
#include "clang/AST/ASTLambda.h"
|
2012-12-01 15:09:41 +00:00
|
|
|
#include "clang/AST/ASTMutationListener.h"
|
2019-11-16 01:31:55 +00:00
|
|
|
#include "clang/AST/Attr.h"
|
2017-11-13 23:01:27 +00:00
|
|
|
#include "clang/AST/CanonicalType.h"
|
|
|
|
#include "clang/AST/DeclBase.h"
|
2012-12-04 09:13:33 +00:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
|
|
|
#include "clang/AST/DeclObjC.h"
|
2016-03-03 05:21:39 +00:00
|
|
|
#include "clang/AST/DeclOpenMP.h"
|
2012-12-04 09:13:33 +00:00
|
|
|
#include "clang/AST/DeclTemplate.h"
|
2017-11-13 23:01:27 +00:00
|
|
|
#include "clang/AST/DeclarationName.h"
|
2008-12-17 23:39:55 +00:00
|
|
|
#include "clang/AST/Expr.h"
|
2009-12-15 19:16:31 +00:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2017-11-13 23:01:27 +00:00
|
|
|
#include "clang/AST/ExternalASTSource.h"
|
2017-12-23 00:41:01 +00:00
|
|
|
#include "clang/AST/ODRHash.h"
|
2018-03-23 00:07:18 +00:00
|
|
|
#include "clang/AST/PrettyDeclStackTrace.h"
|
2009-05-29 20:38:28 +00:00
|
|
|
#include "clang/AST/PrettyPrinter.h"
|
2022-04-09 06:36:51 +00:00
|
|
|
#include "clang/AST/Randstruct.h"
|
2022-04-14 22:20:37 +00:00
|
|
|
#include "clang/AST/RecordLayout.h"
|
2017-11-13 23:01:27 +00:00
|
|
|
#include "clang/AST/Redeclarable.h"
|
2012-12-01 15:09:41 +00:00
|
|
|
#include "clang/AST/Stmt.h"
|
2017-11-13 23:01:27 +00:00
|
|
|
#include "clang/AST/TemplateBase.h"
|
|
|
|
#include "clang/AST/Type.h"
|
2012-12-01 15:09:41 +00:00
|
|
|
#include "clang/AST/TypeLoc.h"
|
2009-06-14 01:54:56 +00:00
|
|
|
#include "clang/Basic/Builtins.h"
|
2008-08-11 04:54:23 +00:00
|
|
|
#include "clang/Basic/IdentifierTable.h"
|
2017-11-13 23:01:27 +00:00
|
|
|
#include "clang/Basic/LLVM.h"
|
|
|
|
#include "clang/Basic/LangOptions.h"
|
|
|
|
#include "clang/Basic/Linkage.h"
|
2011-12-02 23:23:56 +00:00
|
|
|
#include "clang/Basic/Module.h"
|
2021-02-22 19:47:29 +00:00
|
|
|
#include "clang/Basic/NoSanitizeList.h"
|
2017-11-13 23:01:27 +00:00
|
|
|
#include "clang/Basic/PartialDiagnostic.h"
|
|
|
|
#include "clang/Basic/Sanitizers.h"
|
|
|
|
#include "clang/Basic/SourceLocation.h"
|
|
|
|
#include "clang/Basic/SourceManager.h"
|
2010-05-11 21:36:43 +00:00
|
|
|
#include "clang/Basic/Specifiers.h"
|
2017-11-13 23:01:27 +00:00
|
|
|
#include "clang/Basic/TargetCXXABI.h"
|
2011-03-26 12:10:19 +00:00
|
|
|
#include "clang/Basic/TargetInfo.h"
|
2017-11-13 23:01:27 +00:00
|
|
|
#include "clang/Basic/Visibility.h"
|
|
|
|
#include "llvm/ADT/APSInt.h"
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
2019-11-16 01:31:55 +00:00
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
2017-11-13 23:01:27 +00:00
|
|
|
#include "llvm/Support/Casting.h"
|
2009-09-04 01:14:41 +00:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2017-11-13 23:01:27 +00:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2023-02-07 12:21:51 +00:00
|
|
|
#include "llvm/TargetParser/Triple.h"
|
2011-09-21 18:16:56 +00:00
|
|
|
#include <algorithm>
|
2017-11-13 23:01:27 +00:00
|
|
|
#include <cassert>
|
|
|
|
#include <cstddef>
|
|
|
|
#include <cstring>
|
|
|
|
#include <memory>
|
2023-01-14 19:07:21 +00:00
|
|
|
#include <optional>
|
2017-11-13 23:01:27 +00:00
|
|
|
#include <string>
|
|
|
|
#include <tuple>
|
|
|
|
#include <type_traits>
|
2011-09-21 18:16:56 +00:00
|
|
|
|
2006-10-25 05:11:20 +00:00
|
|
|
using namespace clang;
|
2006-10-15 22:34:45 +00:00
|
|
|
|
2013-10-07 08:02:11 +00:00
|
|
|
Decl *clang::getPrimaryMergedDecl(Decl *D) {
|
|
|
|
return D->getASTContext().getPrimaryMergedDecl(D);
|
|
|
|
}
|
|
|
|
|
2018-03-23 00:07:18 +00:00
|
|
|
void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
|
|
|
|
SourceLocation Loc = this->Loc;
|
|
|
|
if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
|
|
|
|
if (Loc.isValid()) {
|
|
|
|
Loc.print(OS, Context.getSourceManager());
|
|
|
|
OS << ": ";
|
|
|
|
}
|
|
|
|
OS << Message;
|
|
|
|
|
2023-09-13 12:53:27 +00:00
|
|
|
if (auto *ND = dyn_cast_if_present<NamedDecl>(TheDecl)) {
|
2018-03-23 00:07:18 +00:00
|
|
|
OS << " '";
|
|
|
|
ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true);
|
|
|
|
OS << "'";
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << '\n';
|
|
|
|
}
|
|
|
|
|
2014-09-03 02:33:22 +00:00
|
|
|
// Defined here so that it can be inlined into its direct callers.
|
|
|
|
bool Decl::isOutOfLine() const {
|
|
|
|
return !getLexicalDeclContext()->Equals(getDeclContext());
|
|
|
|
}
|
|
|
|
|
2015-05-15 20:05:43 +00:00
|
|
|
TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx)
|
|
|
|
: Decl(TranslationUnit, nullptr, SourceLocation()),
|
Reland "[clang-repl] Implement partial translation units and error recovery."
Original commit message:
[clang-repl] Implement partial translation units and error recovery.
https://reviews.llvm.org/D96033 contained a discussion regarding efficient
modeling of error recovery. @rjmccall has outlined the key ideas:
Conceptually, we can split the translation unit into a sequence of partial
translation units (PTUs). Every declaration will be associated with a unique PTU
that owns it.
The first key insight here is that the owning PTU isn't always the "active"
(most recent) PTU, and it isn't always the PTU that the declaration
"comes from". A new declaration (that isn't a redeclaration or specialization of
anything) does belong to the active PTU. A template specialization, however,
belongs to the most recent PTU of all the declarations in its signature - mostly
that means that it can be pulled into a more recent PTU by its template
arguments.
The second key insight is that processing a PTU might extend an earlier PTU.
Rolling back the later PTU shouldn't throw that extension away. For example, if
the second PTU defines a template, and the third PTU requires that template to
be instantiated at float, that template specialization is still part of the
second PTU. Similarly, if the fifth PTU uses an inline function belonging to the
fourth, that definition still belongs to the fourth. When we go to emit code in
a new PTU, we map each declaration we have to emit back to its owning PTU and
emit it in a new module for just the extensions to that PTU. We keep track of
all the modules we've emitted for a PTU so that we can unload them all if we
decide to roll it back.
Most declarations/definitions will only refer to entities from the same or
earlier PTUs. However, it is possible (primarily by defining a
previously-declared entity, but also through templates or ADL) for an entity
that belongs to one PTU to refer to something from a later PTU. We will have to
keep track of this and prevent unwinding to later PTU when we recognize it.
Fortunately, this should be very rare; and crucially, we don't have to do the
bookkeeping for this if we've only got one PTU, e.g. in normal compilation.
Otherwise, PTUs after the first just need to record enough metadata to be able
to revert any changes they've made to declarations belonging to earlier PTUs,
e.g. to redeclaration chains or template specialization lists.
It should even eventually be possible for PTUs to provide their own slab
allocators which can be thrown away as part of rolling back the PTU. We can
maintain a notion of the active allocator and allocate things like Stmt/Expr
nodes in it, temporarily changing it to the appropriate PTU whenever we go to do
something like instantiate a function template. More care will be required when
allocating declarations and types, though.
We would want the PTU to be efficiently recoverable from a Decl; I'm not sure
how best to do that. An easy option that would cover most declarations would be
to make multiple TranslationUnitDecls and parent the declarations appropriately,
but I don't think that's good enough for things like member function templates,
since an instantiation of that would still be parented by its original class.
Maybe we can work this into the DC chain somehow, like how lexical DCs are.
We add a different kind of translation unit `TU_Incremental` which is a
complete translation unit that we might nonetheless incrementally extend later.
Because it is complete (and we might want to generate code for it), we do
perform template instantiation, but because it might be extended later, we don't
warn if it declares or uses undefined internal-linkage symbols.
This patch teaches clang-repl how to recover from errors by disconnecting the
most recent PTU and update the primary PTU lookup tables. For instance:
```./clang-repl
clang-repl> int i = 12; error;
In file included from <<< inputs >>>:1:
input_line_0:1:13: error: C++ requires a type specifier for all declarations
int i = 12; error;
^
error: Parsing failed.
clang-repl> int i = 13; extern "C" int printf(const char*,...);
clang-repl> auto r1 = printf("i=%d\n", i);
i=13
clang-repl> quit
```
Differential revision: https://reviews.llvm.org/D104918
2021-07-12 13:35:20 +00:00
|
|
|
DeclContext(TranslationUnit), redeclarable_base(ctx), Ctx(ctx) {}
|
2015-05-15 20:05:43 +00:00
|
|
|
|
2008-03-31 00:36:02 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
2009-01-20 01:17:11 +00:00
|
|
|
// NamedDecl Implementation
|
2008-11-09 23:41:00 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-02-16 00:17:33 +00:00
|
|
|
// Visibility rules aren't rigorously externally specified, but here
|
|
|
|
// are the basic principles behind what we implement:
|
|
|
|
//
|
|
|
|
// 1. An explicit visibility attribute is generally a direct expression
|
|
|
|
// of the user's intent and should be honored. Only the innermost
|
|
|
|
// visibility attribute applies. If no visibility attribute applies,
|
|
|
|
// global visibility settings are considered.
|
|
|
|
//
|
|
|
|
// 2. There is one caveat to the above: on or in a template pattern,
|
|
|
|
// an explicit visibility attribute is just a default rule, and
|
|
|
|
// visibility can be decreased by the visibility of template
|
|
|
|
// arguments. But this, too, has an exception: an attribute on an
|
|
|
|
// explicit specialization or instantiation causes all the visibility
|
|
|
|
// restrictions of the template arguments to be ignored.
|
|
|
|
//
|
|
|
|
// 3. A variable that does not otherwise have explicit visibility can
|
|
|
|
// be restricted by the visibility of its type.
|
|
|
|
//
|
|
|
|
// 4. A visibility restriction is explicit if it comes from an
|
|
|
|
// attribute (or something like it), not a global visibility setting.
|
|
|
|
// When emitting a reference to an external symbol, visibility
|
|
|
|
// restrictions are ignored unless they are explicit.
|
2013-02-20 01:54:26 +00:00
|
|
|
//
|
|
|
|
// 5. When computing the visibility of a non-type, including a
|
|
|
|
// non-type member of a class, only non-type visibility restrictions
|
|
|
|
// are considered: the 'visibility' attribute, global value-visibility
|
|
|
|
// settings, and a few special cases like __private_extern.
|
|
|
|
//
|
|
|
|
// 6. When computing the visibility of a type, including a type member
|
|
|
|
// of a class, only type visibility restrictions are considered:
|
|
|
|
// the 'type_visibility' attribute and global type-visibility settings.
|
|
|
|
// However, a 'visibility' attribute counts as a 'type_visibility'
|
|
|
|
// attribute on any declaration that only has the former.
|
|
|
|
//
|
|
|
|
// The visibility of a "secondary" entity, like a template argument,
|
|
|
|
// is computed using the kind of that entity, not the kind of the
|
|
|
|
// primary entity for which we are computing visibility. For example,
|
|
|
|
// the visibility of a specialization of either of these templates:
|
|
|
|
// template <class T, bool (&compare)(T, X)> bool has_match(list<T>, X);
|
|
|
|
// template <class T, bool (&compare)(T, X)> class matcher;
|
|
|
|
// is restricted according to the type visibility of the argument 'T',
|
|
|
|
// the type visibility of 'bool(&)(T,X)', and the value visibility of
|
|
|
|
// the argument function 'compare'. That 'has_match' is a value
|
|
|
|
// and 'matcher' is a type only matters when looking for attributes
|
|
|
|
// and settings from the immediate context.
|
2013-02-16 00:17:33 +00:00
|
|
|
|
2013-02-20 01:54:26 +00:00
|
|
|
/// Does this computation kind permit us to consider additional
|
|
|
|
/// visibility settings from attributes and the like?
|
|
|
|
static bool hasExplicitVisibilityAlready(LVComputationKind computation) {
|
2017-09-22 02:22:32 +00:00
|
|
|
return computation.IgnoreExplicitVisibility;
|
2013-02-20 01:54:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Given an LVComputationKind, return one of the same type/value sort
|
|
|
|
/// that records that it already has explicit visibility.
|
|
|
|
static LVComputationKind
|
2017-09-22 02:22:32 +00:00
|
|
|
withExplicitVisibilityAlready(LVComputationKind Kind) {
|
|
|
|
Kind.IgnoreExplicitVisibility = true;
|
|
|
|
return Kind;
|
2013-02-20 01:54:26 +00:00
|
|
|
}
|
|
|
|
|
2023-01-14 20:31:01 +00:00
|
|
|
static std::optional<Visibility> getExplicitVisibility(const NamedDecl *D,
|
|
|
|
LVComputationKind kind) {
|
2017-09-22 02:22:32 +00:00
|
|
|
assert(!kind.IgnoreExplicitVisibility &&
|
2013-02-20 01:54:26 +00:00
|
|
|
"asking for explicit visibility when we shouldn't be");
|
2017-09-22 02:22:32 +00:00
|
|
|
return D->getExplicitVisibility(kind.getExplicitVisibilityKind());
|
2013-02-20 01:54:26 +00:00
|
|
|
}
|
|
|
|
|
2013-02-16 00:17:33 +00:00
|
|
|
/// Is the given declaration a "type" or a "value" for the purposes of
|
|
|
|
/// visibility computation?
|
|
|
|
static bool usesTypeVisibility(const NamedDecl *D) {
|
2013-02-19 01:57:35 +00:00
|
|
|
return isa<TypeDecl>(D) ||
|
|
|
|
isa<ClassTemplateDecl>(D) ||
|
|
|
|
isa<ObjCInterfaceDecl>(D);
|
2013-02-16 00:17:33 +00:00
|
|
|
}
|
|
|
|
|
2013-02-21 23:42:58 +00:00
|
|
|
/// Does the given declaration have member specialization information,
|
|
|
|
/// and if so, is it an explicit specialization?
|
2022-10-02 00:24:54 +00:00
|
|
|
template <class T>
|
2022-11-07 18:25:46 +00:00
|
|
|
static std::enable_if_t<!std::is_base_of_v<RedeclarableTemplateDecl, T>, bool>
|
2013-02-21 23:42:58 +00:00
|
|
|
isExplicitMemberSpecialization(const T *D) {
|
|
|
|
if (const MemberSpecializationInfo *member =
|
|
|
|
D->getMemberSpecializationInfo()) {
|
|
|
|
return member->isExplicitSpecialization();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// For templates, this question is easier: a member template can't be
|
|
|
|
/// explicitly instantiated, so there's a single bit indicating whether
|
|
|
|
/// or not this is an explicit member specialization.
|
|
|
|
static bool isExplicitMemberSpecialization(const RedeclarableTemplateDecl *D) {
|
|
|
|
return D->isMemberSpecialization();
|
|
|
|
}
|
|
|
|
|
2013-02-20 01:54:26 +00:00
|
|
|
/// Given a visibility attribute, return the explicit visibility
|
|
|
|
/// associated with it.
|
|
|
|
template <class T>
|
|
|
|
static Visibility getVisibilityFromAttr(const T *attr) {
|
|
|
|
switch (attr->getVisibility()) {
|
|
|
|
case T::Default:
|
|
|
|
return DefaultVisibility;
|
|
|
|
case T::Hidden:
|
|
|
|
return HiddenVisibility;
|
|
|
|
case T::Protected:
|
|
|
|
return ProtectedVisibility;
|
|
|
|
}
|
|
|
|
llvm_unreachable("bad visibility kind");
|
|
|
|
}
|
|
|
|
|
2013-02-16 00:17:33 +00:00
|
|
|
/// Return the explicit visibility of the given declaration.
|
2023-01-14 20:31:01 +00:00
|
|
|
static std::optional<Visibility>
|
|
|
|
getVisibilityOf(const NamedDecl *D, NamedDecl::ExplicitVisibilityKind kind) {
|
2013-02-20 01:54:26 +00:00
|
|
|
// If we're ultimately computing the visibility of a type, look for
|
|
|
|
// a 'type_visibility' attribute before looking for 'visibility'.
|
|
|
|
if (kind == NamedDecl::VisibilityForType) {
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *A = D->getAttr<TypeVisibilityAttr>()) {
|
2013-02-20 01:54:26 +00:00
|
|
|
return getVisibilityFromAttr(A);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-26 12:10:19 +00:00
|
|
|
// If this declaration has an explicit visibility attribute, use it.
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *A = D->getAttr<VisibilityAttr>()) {
|
2013-02-20 01:54:26 +00:00
|
|
|
return getVisibilityFromAttr(A);
|
2010-10-28 04:18:25 +00:00
|
|
|
}
|
2010-12-18 03:30:47 +00:00
|
|
|
|
2022-12-03 19:13:41 +00:00
|
|
|
return std::nullopt;
|
2010-10-22 21:05:15 +00:00
|
|
|
}
|
|
|
|
|
2017-08-09 04:02:49 +00:00
|
|
|
LinkageInfo LinkageComputer::getLVForType(const Type &T,
|
|
|
|
LVComputationKind computation) {
|
2017-09-22 02:22:32 +00:00
|
|
|
if (computation.IgnoreAllVisibility)
|
2013-05-29 04:55:30 +00:00
|
|
|
return LinkageInfo(T.getLinkage(), DefaultVisibility, true);
|
2017-08-09 04:12:17 +00:00
|
|
|
return getTypeLinkageAndVisibility(&T);
|
2013-05-29 04:55:30 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Get the most restrictive linkage for the types in the given
|
2013-02-16 00:17:33 +00:00
|
|
|
/// template parameter list. For visibility purposes, template
|
|
|
|
/// parameters are part of the signature of a template.
|
2017-08-09 04:02:49 +00:00
|
|
|
LinkageInfo LinkageComputer::getLVForTemplateParameterList(
|
|
|
|
const TemplateParameterList *Params, LVComputationKind computation) {
|
2013-02-16 00:17:33 +00:00
|
|
|
LinkageInfo LV;
|
2014-04-23 05:16:48 +00:00
|
|
|
for (const NamedDecl *P : *Params) {
|
2013-02-16 00:17:33 +00:00
|
|
|
// Template type parameters are the most common and never
|
|
|
|
// contribute to visibility, pack or not.
|
2014-04-23 05:16:48 +00:00
|
|
|
if (isa<TemplateTypeParmDecl>(P))
|
2013-02-16 00:17:33 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Non-type template parameters can be restricted by the value type, e.g.
|
|
|
|
// template <enum X> class A { ... };
|
|
|
|
// We have to be careful here, though, because we can be dealing with
|
|
|
|
// dependent types.
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
|
2013-02-16 00:17:33 +00:00
|
|
|
// Handle the non-pack case first.
|
|
|
|
if (!NTTP->isExpandedParameterPack()) {
|
|
|
|
if (!NTTP->getType()->isDependentType()) {
|
2013-05-29 04:55:30 +00:00
|
|
|
LV.merge(getLVForType(*NTTP->getType(), computation));
|
2011-01-19 20:10:05 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2012-01-02 06:26:22 +00:00
|
|
|
|
2013-02-16 00:17:33 +00:00
|
|
|
// Look at all the types in an expanded pack.
|
|
|
|
for (unsigned i = 0, n = NTTP->getNumExpansionTypes(); i != n; ++i) {
|
|
|
|
QualType type = NTTP->getExpansionType(i);
|
|
|
|
if (!type->isDependentType())
|
2017-08-09 04:12:17 +00:00
|
|
|
LV.merge(getTypeLinkageAndVisibility(type));
|
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
|
|
|
}
|
2013-02-16 00:17:33 +00:00
|
|
|
continue;
|
2011-01-19 20:10:05 +00:00
|
|
|
}
|
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
|
|
|
|
2013-02-16 00:17:33 +00:00
|
|
|
// Template template parameters can be restricted by their
|
|
|
|
// template parameters, recursively.
|
2015-11-09 17:53:06 +00:00
|
|
|
const auto *TTP = cast<TemplateTemplateParmDecl>(P);
|
2013-02-16 00:17:33 +00:00
|
|
|
|
|
|
|
// Handle the non-pack case first.
|
|
|
|
if (!TTP->isExpandedParameterPack()) {
|
2013-05-29 04:55:30 +00:00
|
|
|
LV.merge(getLVForTemplateParameterList(TTP->getTemplateParameters(),
|
|
|
|
computation));
|
2013-02-16 00:17:33 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look at all expansions in an expanded pack.
|
|
|
|
for (unsigned i = 0, n = TTP->getNumExpansionTemplateParameters();
|
|
|
|
i != n; ++i) {
|
|
|
|
LV.merge(getLVForTemplateParameterList(
|
2013-05-29 04:55:30 +00:00
|
|
|
TTP->getExpansionTemplateParameters(i), computation));
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-22 21:05:15 +00:00
|
|
|
return LV;
|
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
|
|
|
}
|
|
|
|
|
2013-07-01 20:22:57 +00:00
|
|
|
static const Decl *getOutermostFuncOrBlockContext(const Decl *D) {
|
2014-05-12 05:36:57 +00:00
|
|
|
const Decl *Ret = nullptr;
|
2013-05-16 04:30:21 +00:00
|
|
|
const DeclContext *DC = D->getDeclContext();
|
|
|
|
while (DC->getDeclKind() != Decl::TranslationUnit) {
|
2013-07-01 20:22:57 +00:00
|
|
|
if (isa<FunctionDecl>(DC) || isa<BlockDecl>(DC))
|
|
|
|
Ret = cast<Decl>(DC);
|
2013-05-16 04:30:21 +00:00
|
|
|
DC = DC->getParent();
|
|
|
|
}
|
|
|
|
return Ret;
|
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Get the most restrictive linkage for the types and
|
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
|
|
|
/// declarations in the given template argument list.
|
2013-02-16 00:17:33 +00:00
|
|
|
///
|
|
|
|
/// Note that we don't take an LVComputationKind because we always
|
|
|
|
/// want to honor the visibility of template arguments in the same way.
|
2017-08-09 04:02:49 +00:00
|
|
|
LinkageInfo
|
|
|
|
LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
|
|
|
|
LVComputationKind computation) {
|
2013-02-16 00:17:33 +00:00
|
|
|
LinkageInfo LV;
|
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
|
|
|
|
2014-04-23 05:16:48 +00:00
|
|
|
for (const TemplateArgument &Arg : Args) {
|
|
|
|
switch (Arg.getKind()) {
|
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
|
|
|
case TemplateArgument::Null:
|
|
|
|
case TemplateArgument::Integral:
|
|
|
|
case TemplateArgument::Expression:
|
2013-02-16 00:17:33 +00:00
|
|
|
continue;
|
2012-01-02 06:26:22 +00:00
|
|
|
|
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
|
|
|
case TemplateArgument::Type:
|
2014-04-23 05:16:48 +00:00
|
|
|
LV.merge(getLVForType(*Arg.getAsType(), computation));
|
2013-02-16 00:17:33 +00:00
|
|
|
continue;
|
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
|
|
|
|
2018-03-01 05:43:23 +00:00
|
|
|
case TemplateArgument::Declaration: {
|
|
|
|
const NamedDecl *ND = Arg.getAsDecl();
|
|
|
|
assert(!usesTypeVisibility(ND));
|
|
|
|
LV.merge(getLVForDecl(ND, computation));
|
2013-02-16 00:17:33 +00:00
|
|
|
continue;
|
2018-03-01 05:43:23 +00:00
|
|
|
}
|
2012-09-26 02:36:12 +00:00
|
|
|
|
|
|
|
case TemplateArgument::NullPtr:
|
2017-08-09 04:12:17 +00:00
|
|
|
LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType()));
|
2013-02-16 00:17:33 +00:00
|
|
|
continue;
|
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
|
|
|
|
|
|
|
case TemplateArgument::Template:
|
2011-01-05 18:58:31 +00:00
|
|
|
case TemplateArgument::TemplateExpansion:
|
2014-04-23 05:16:48 +00:00
|
|
|
if (TemplateDecl *Template =
|
|
|
|
Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
|
2013-05-29 04:55:30 +00:00
|
|
|
LV.merge(getLVForDecl(Template, computation));
|
2013-02-16 00:17:33 +00:00
|
|
|
continue;
|
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
|
|
|
|
|
|
|
case TemplateArgument::Pack:
|
2014-04-23 05:16:48 +00:00
|
|
|
LV.merge(getLVForTemplateArgumentList(Arg.getPackAsArray(), computation));
|
2013-02-16 00:17:33 +00:00
|
|
|
continue;
|
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
|
|
|
}
|
2013-02-16 00:17:33 +00:00
|
|
|
llvm_unreachable("bad template argument kind");
|
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
|
|
|
}
|
|
|
|
|
2010-10-22 21:05:15 +00:00
|
|
|
return LV;
|
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
|
|
|
}
|
|
|
|
|
2017-08-09 04:02:49 +00:00
|
|
|
LinkageInfo
|
|
|
|
LinkageComputer::getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
|
|
|
|
LVComputationKind computation) {
|
2013-05-29 04:55:30 +00:00
|
|
|
return getLVForTemplateArgumentList(TArgs.asArray(), computation);
|
2010-08-13 08:35:10 +00:00
|
|
|
}
|
|
|
|
|
2013-02-21 23:42:58 +00:00
|
|
|
static bool shouldConsiderTemplateVisibility(const FunctionDecl *fn,
|
|
|
|
const FunctionTemplateSpecializationInfo *specInfo) {
|
|
|
|
// Include visibility from the template parameters and arguments
|
|
|
|
// only if this is not an explicit instantiation or specialization
|
|
|
|
// with direct explicit visibility. (Implicit instantiations won't
|
|
|
|
// have a direct attribute.)
|
|
|
|
if (!specInfo->isExplicitInstantiationOrSpecialization())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return !fn->hasAttr<VisibilityAttr>();
|
|
|
|
}
|
|
|
|
|
2013-02-16 00:17:33 +00:00
|
|
|
/// Merge in template-related linkage and visibility for the given
|
|
|
|
/// function template specialization.
|
|
|
|
///
|
|
|
|
/// We don't need a computation kind here because we can assume
|
|
|
|
/// LVForValue.
|
2013-02-21 23:42:58 +00:00
|
|
|
///
|
2013-02-22 04:06:28 +00:00
|
|
|
/// \param[out] LV the computation to use for the parent
|
2017-08-09 04:02:49 +00:00
|
|
|
void LinkageComputer::mergeTemplateLV(
|
|
|
|
LinkageInfo &LV, const FunctionDecl *fn,
|
|
|
|
const FunctionTemplateSpecializationInfo *specInfo,
|
|
|
|
LVComputationKind computation) {
|
2013-02-21 23:42:58 +00:00
|
|
|
bool considerVisibility =
|
|
|
|
shouldConsiderTemplateVisibility(fn, specInfo);
|
2013-02-16 00:17:33 +00:00
|
|
|
|
2013-02-21 23:42:58 +00:00
|
|
|
FunctionTemplateDecl *temp = specInfo->getTemplate();
|
2022-02-23 08:23:26 +00:00
|
|
|
// Merge information from the template declaration.
|
|
|
|
LinkageInfo tempLV = getLVForDecl(temp, computation);
|
|
|
|
// The linkage of the specialization should be consistent with the
|
|
|
|
// template declaration.
|
|
|
|
LV.setLinkage(tempLV.getLinkage());
|
|
|
|
|
|
|
|
// Merge information from the template parameters.
|
|
|
|
LinkageInfo paramsLV =
|
|
|
|
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
|
|
|
|
LV.mergeMaybeWithVisibility(paramsLV, considerVisibility);
|
2013-02-16 00:17:33 +00:00
|
|
|
|
|
|
|
// Merge information from the template arguments.
|
|
|
|
const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments;
|
2013-05-29 04:55:30 +00:00
|
|
|
LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
|
2013-02-16 00:17:33 +00:00
|
|
|
LV.mergeMaybeWithVisibility(argsLV, considerVisibility);
|
2011-06-27 23:06:04 +00:00
|
|
|
}
|
|
|
|
|
2013-02-21 23:42:58 +00:00
|
|
|
/// Does the given declaration have a direct visibility attribute
|
|
|
|
/// that would match the given rules?
|
|
|
|
static bool hasDirectVisibilityAttribute(const NamedDecl *D,
|
|
|
|
LVComputationKind computation) {
|
2017-09-22 02:22:32 +00:00
|
|
|
if (computation.IgnoreAllVisibility)
|
2013-02-21 23:42:58 +00:00
|
|
|
return false;
|
2017-09-22 02:22:32 +00:00
|
|
|
|
|
|
|
return (computation.isTypeVisibility() && D->hasAttr<TypeVisibilityAttr>()) ||
|
|
|
|
D->hasAttr<VisibilityAttr>();
|
2013-02-21 23:42:58 +00:00
|
|
|
}
|
|
|
|
|
2013-02-20 01:54:26 +00:00
|
|
|
/// Should we consider visibility associated with the template
|
|
|
|
/// arguments and parameters of the given class template specialization?
|
|
|
|
static bool shouldConsiderTemplateVisibility(
|
|
|
|
const ClassTemplateSpecializationDecl *spec,
|
|
|
|
LVComputationKind computation) {
|
2013-02-16 00:17:33 +00:00
|
|
|
// Include visibility from the template parameters and arguments
|
|
|
|
// only if this is not an explicit instantiation or specialization
|
|
|
|
// with direct explicit visibility (and note that implicit
|
|
|
|
// instantiations won't have a direct attribute).
|
|
|
|
//
|
|
|
|
// Furthermore, we want to ignore template parameters and arguments
|
2013-02-20 01:54:26 +00:00
|
|
|
// for an explicit specialization when computing the visibility of a
|
|
|
|
// member thereof with explicit visibility.
|
2013-02-16 00:17:33 +00:00
|
|
|
//
|
|
|
|
// This is a bit complex; let's unpack it.
|
|
|
|
//
|
|
|
|
// An explicit class specialization is an independent, top-level
|
|
|
|
// declaration. As such, if it or any of its members has an
|
|
|
|
// explicit visibility attribute, that must directly express the
|
|
|
|
// user's intent, and we should honor it. The same logic applies to
|
|
|
|
// an explicit instantiation of a member of such a thing.
|
2013-02-20 01:54:26 +00:00
|
|
|
|
|
|
|
// Fast path: if this is not an explicit instantiation or
|
|
|
|
// specialization, we always want to consider template-related
|
|
|
|
// visibility restrictions.
|
|
|
|
if (!spec->isExplicitInstantiationOrSpecialization())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// This is the 'member thereof' check.
|
|
|
|
if (spec->isExplicitSpecialization() &&
|
|
|
|
hasExplicitVisibilityAlready(computation))
|
|
|
|
return false;
|
|
|
|
|
2013-02-21 23:42:58 +00:00
|
|
|
return !hasDirectVisibilityAttribute(spec, computation);
|
2013-02-20 01:54:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Merge in template-related linkage and visibility for the given
|
|
|
|
/// class template specialization.
|
2017-08-09 04:02:49 +00:00
|
|
|
void LinkageComputer::mergeTemplateLV(
|
|
|
|
LinkageInfo &LV, const ClassTemplateSpecializationDecl *spec,
|
|
|
|
LVComputationKind computation) {
|
2013-02-20 01:54:26 +00:00
|
|
|
bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation);
|
2013-02-16 00:17:33 +00:00
|
|
|
|
|
|
|
// Merge information from the template parameters, but ignore
|
|
|
|
// visibility if we're only considering template arguments.
|
2013-02-20 01:54:26 +00:00
|
|
|
ClassTemplateDecl *temp = spec->getSpecializedTemplate();
|
2022-07-25 09:43:52 +00:00
|
|
|
// Merge information from the template declaration.
|
|
|
|
LinkageInfo tempLV = getLVForDecl(temp, computation);
|
|
|
|
// The linkage of the specialization should be consistent with the
|
|
|
|
// template declaration.
|
|
|
|
LV.setLinkage(tempLV.getLinkage());
|
|
|
|
|
|
|
|
LinkageInfo paramsLV =
|
2013-05-29 04:55:30 +00:00
|
|
|
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
|
2022-07-25 09:43:52 +00:00
|
|
|
LV.mergeMaybeWithVisibility(paramsLV,
|
2013-02-20 01:54:26 +00:00
|
|
|
considerVisibility && !hasExplicitVisibilityAlready(computation));
|
2013-02-16 00:17:33 +00:00
|
|
|
|
|
|
|
// Merge information from the template arguments. We ignore
|
|
|
|
// template-argument visibility if we've got an explicit
|
|
|
|
// instantiation with a visibility attribute.
|
|
|
|
const TemplateArgumentList &templateArgs = spec->getTemplateArgs();
|
2013-05-29 04:55:30 +00:00
|
|
|
LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
|
2013-05-30 21:23:15 +00:00
|
|
|
if (considerVisibility)
|
|
|
|
LV.mergeVisibility(argsLV);
|
|
|
|
LV.mergeExternalVisibility(argsLV);
|
2011-06-27 23:06:04 +00:00
|
|
|
}
|
|
|
|
|
2014-07-02 23:08:34 +00:00
|
|
|
/// Should we consider visibility associated with the template
|
|
|
|
/// arguments and parameters of the given variable template
|
|
|
|
/// specialization? As usual, follow class template specialization
|
|
|
|
/// logic up to initialization.
|
|
|
|
static bool shouldConsiderTemplateVisibility(
|
|
|
|
const VarTemplateSpecializationDecl *spec,
|
|
|
|
LVComputationKind computation) {
|
|
|
|
// Include visibility from the template parameters and arguments
|
|
|
|
// only if this is not an explicit instantiation or specialization
|
|
|
|
// with direct explicit visibility (and note that implicit
|
|
|
|
// instantiations won't have a direct attribute).
|
|
|
|
if (!spec->isExplicitInstantiationOrSpecialization())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// An explicit variable specialization is an independent, top-level
|
|
|
|
// declaration. As such, if it has an explicit visibility attribute,
|
|
|
|
// that must directly express the user's intent, and we should honor
|
|
|
|
// it.
|
|
|
|
if (spec->isExplicitSpecialization() &&
|
|
|
|
hasExplicitVisibilityAlready(computation))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return !hasDirectVisibilityAttribute(spec, computation);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Merge in template-related linkage and visibility for the given
|
|
|
|
/// variable template specialization. As usual, follow class template
|
|
|
|
/// specialization logic up to initialization.
|
2017-08-09 04:02:49 +00:00
|
|
|
void LinkageComputer::mergeTemplateLV(LinkageInfo &LV,
|
|
|
|
const VarTemplateSpecializationDecl *spec,
|
|
|
|
LVComputationKind computation) {
|
2014-07-02 23:08:34 +00:00
|
|
|
bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation);
|
|
|
|
|
|
|
|
// Merge information from the template parameters, but ignore
|
|
|
|
// visibility if we're only considering template arguments.
|
|
|
|
VarTemplateDecl *temp = spec->getSpecializedTemplate();
|
|
|
|
LinkageInfo tempLV =
|
|
|
|
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
|
|
|
|
LV.mergeMaybeWithVisibility(tempLV,
|
|
|
|
considerVisibility && !hasExplicitVisibilityAlready(computation));
|
|
|
|
|
|
|
|
// Merge information from the template arguments. We ignore
|
|
|
|
// template-argument visibility if we've got an explicit
|
|
|
|
// instantiation with a visibility attribute.
|
|
|
|
const TemplateArgumentList &templateArgs = spec->getTemplateArgs();
|
|
|
|
LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
|
|
|
|
if (considerVisibility)
|
|
|
|
LV.mergeVisibility(argsLV);
|
|
|
|
LV.mergeExternalVisibility(argsLV);
|
|
|
|
}
|
|
|
|
|
2012-07-13 14:25:36 +00:00
|
|
|
static bool useInlineVisibilityHidden(const NamedDecl *D) {
|
|
|
|
// FIXME: we should warn if -fvisibility-inlines-hidden is used with c.
|
2012-07-13 23:26:43 +00:00
|
|
|
const LangOptions &Opts = D->getASTContext().getLangOpts();
|
|
|
|
if (!Opts.CPlusPlus || !Opts.InlineVisibilityHidden)
|
2012-07-13 14:25:36 +00:00
|
|
|
return false;
|
|
|
|
|
2015-11-09 17:53:06 +00:00
|
|
|
const auto *FD = dyn_cast<FunctionDecl>(D);
|
2012-07-13 14:25:36 +00:00
|
|
|
if (!FD)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
TemplateSpecializationKind TSK = TSK_Undeclared;
|
|
|
|
if (FunctionTemplateSpecializationInfo *spec
|
|
|
|
= FD->getTemplateSpecializationInfo()) {
|
|
|
|
TSK = spec->getTemplateSpecializationKind();
|
|
|
|
} else if (MemberSpecializationInfo *MSI =
|
|
|
|
FD->getMemberSpecializationInfo()) {
|
|
|
|
TSK = MSI->getTemplateSpecializationKind();
|
|
|
|
}
|
|
|
|
|
2014-05-12 05:36:57 +00:00
|
|
|
const FunctionDecl *Def = nullptr;
|
2012-07-13 14:25:36 +00:00
|
|
|
// InlineVisibilityHidden only applies to definitions, and
|
|
|
|
// isInlined() only gives meaningful answers on definitions
|
|
|
|
// anyway.
|
|
|
|
return TSK != TSK_ExplicitInstantiationDeclaration &&
|
|
|
|
TSK != TSK_ExplicitInstantiationDefinition &&
|
2012-10-11 16:32:25 +00:00
|
|
|
FD->hasBody(Def) && Def->isInlined() && !Def->hasAttr<GNUInlineAttr>();
|
2012-07-13 14:25:36 +00:00
|
|
|
}
|
|
|
|
|
2013-05-05 20:15:21 +00:00
|
|
|
template <typename T> static bool isFirstInExternCContext(T *D) {
|
2013-10-17 15:37:26 +00:00
|
|
|
const T *First = D->getFirstDecl();
|
2013-05-05 20:15:21 +00:00
|
|
|
return First->isInExternCContext();
|
2013-02-14 01:18:37 +00:00
|
|
|
}
|
|
|
|
|
2014-02-17 23:34:47 +00:00
|
|
|
static bool isSingleLineLanguageLinkage(const Decl &D) {
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext()))
|
2014-02-17 23:34:47 +00:00
|
|
|
if (!SD->hasBraces())
|
2013-04-26 01:30:23 +00:00
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-04-18 21:12:54 +00:00
|
|
|
/// Determine whether D is declared in the purview of a named module.
|
|
|
|
static bool isInModulePurview(const NamedDecl *D) {
|
|
|
|
if (auto *M = D->getOwningModule())
|
|
|
|
return M->isModulePurview();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-04-19 02:15:57 +00:00
|
|
|
static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
|
2017-10-10 22:33:17 +00:00
|
|
|
// FIXME: Handle isModulePrivate.
|
2017-07-07 20:04:28 +00:00
|
|
|
switch (D->getModuleOwnershipKind()) {
|
|
|
|
case Decl::ModuleOwnershipKind::Unowned:
|
2022-06-29 04:48:48 +00:00
|
|
|
case Decl::ModuleOwnershipKind::ReachableWhenImported:
|
2017-07-07 20:04:28 +00:00
|
|
|
case Decl::ModuleOwnershipKind::ModulePrivate:
|
|
|
|
return false;
|
|
|
|
case Decl::ModuleOwnershipKind::Visible:
|
|
|
|
case Decl::ModuleOwnershipKind::VisibleWhenImported:
|
2019-04-18 21:12:54 +00:00
|
|
|
return isInModulePurview(D);
|
2017-07-07 20:04:28 +00:00
|
|
|
}
|
|
|
|
llvm_unreachable("unexpected module ownership kind");
|
|
|
|
}
|
|
|
|
|
2023-03-12 20:45:26 +00:00
|
|
|
static bool isDeclaredInModuleInterfaceOrPartition(const NamedDecl *D) {
|
|
|
|
if (auto *M = D->getOwningModule())
|
|
|
|
return M->isInterfaceOrPartition();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-07-07 20:04:28 +00:00
|
|
|
static LinkageInfo getExternalLinkageFor(const NamedDecl *D) {
|
|
|
|
return LinkageInfo::external();
|
|
|
|
}
|
|
|
|
|
2019-04-26 01:51:08 +00:00
|
|
|
static StorageClass getStorageClass(const Decl *D) {
|
|
|
|
if (auto *TD = dyn_cast<TemplateDecl>(D))
|
|
|
|
D = TD->getTemplatedDecl();
|
2019-05-14 10:11:33 +00:00
|
|
|
if (D) {
|
|
|
|
if (auto *VD = dyn_cast<VarDecl>(D))
|
|
|
|
return VD->getStorageClass();
|
|
|
|
if (auto *FD = dyn_cast<FunctionDecl>(D))
|
|
|
|
return FD->getStorageClass();
|
2019-04-26 01:51:08 +00:00
|
|
|
}
|
2021-01-04 22:17:45 +00:00
|
|
|
return SC_None;
|
2019-04-26 01:51:08 +00:00
|
|
|
}
|
|
|
|
|
2017-08-09 04:02:49 +00:00
|
|
|
LinkageInfo
|
|
|
|
LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
2017-09-22 04:25:05 +00:00
|
|
|
LVComputationKind computation,
|
|
|
|
bool IgnoreVarTypeLinkage) {
|
2010-08-31 00:36:30 +00:00
|
|
|
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
|
2009-11-25 22:24:25 +00:00
|
|
|
"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
|
2019-04-26 01:51:08 +00:00
|
|
|
|
2021-01-04 22:17:45 +00:00
|
|
|
if (getStorageClass(D->getCanonicalDecl()) == SC_Static) {
|
2019-04-26 01:51:08 +00:00
|
|
|
// - a variable, variable template, function, or function template
|
|
|
|
// that is explicitly declared static; or
|
|
|
|
// (This bullet corresponds to C99 6.2.2p3.)
|
2023-07-09 00:26:36 +00:00
|
|
|
return LinkageInfo::internal();
|
2019-04-26 01:51:08 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *Var = dyn_cast<VarDecl>(D)) {
|
2019-04-26 01:51:08 +00:00
|
|
|
// - a non-template variable of non-volatile const-qualified type, unless
|
|
|
|
// - it is explicitly declared extern, or
|
2023-03-12 20:45:26 +00:00
|
|
|
// - it is declared in the purview of a module interface unit
|
|
|
|
// (outside the private-module-fragment, if any) or module partition, or
|
|
|
|
// - it is inline, or
|
2019-04-26 01:51:08 +00:00
|
|
|
// - it was previously declared and the prior declaration did not have
|
|
|
|
// internal linkage
|
|
|
|
// (There is no equivalent in C99.)
|
2023-03-12 20:45:26 +00:00
|
|
|
if (Context.getLangOpts().CPlusPlus && Var->getType().isConstQualified() &&
|
|
|
|
!Var->getType().isVolatileQualified() && !Var->isInline() &&
|
|
|
|
!isDeclaredInModuleInterfaceOrPartition(Var) &&
|
2019-04-26 01:51:08 +00:00
|
|
|
!isa<VarTemplateSpecializationDecl>(Var) &&
|
|
|
|
!Var->getDescribedVarTemplate()) {
|
2013-04-03 19:22:20 +00:00
|
|
|
const VarDecl *PrevVar = Var->getPreviousDecl();
|
|
|
|
if (PrevVar)
|
2013-05-29 04:55:30 +00:00
|
|
|
return getLVForDecl(PrevVar, computation);
|
2013-04-03 19:27:57 +00:00
|
|
|
|
2021-01-04 22:17:45 +00:00
|
|
|
if (Var->getStorageClass() != SC_Extern &&
|
|
|
|
Var->getStorageClass() != SC_PrivateExtern &&
|
2014-02-17 23:34:47 +00:00
|
|
|
!isSingleLineLanguageLinkage(*Var))
|
2023-07-09 00:26:36 +00:00
|
|
|
return LinkageInfo::internal();
|
2013-04-03 19:27:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar;
|
|
|
|
PrevVar = PrevVar->getPreviousDecl()) {
|
2021-01-04 22:17:45 +00:00
|
|
|
if (PrevVar->getStorageClass() == SC_PrivateExtern &&
|
|
|
|
Var->getStorageClass() == SC_None)
|
2017-08-09 04:12:17 +00:00
|
|
|
return getDeclLinkageAndVisibility(PrevVar);
|
2013-04-03 19:27:57 +00:00
|
|
|
// Explicitly declared static.
|
2021-01-04 22:17:45 +00:00
|
|
|
if (PrevVar->getStorageClass() == SC_Static)
|
2023-07-09 00:26:36 +00:00
|
|
|
return LinkageInfo::internal();
|
2011-06-16 20:14:50 +00:00
|
|
|
}
|
2014-12-10 22:58:14 +00:00
|
|
|
} else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) {
|
|
|
|
// - a data member of an anonymous union.
|
|
|
|
const VarDecl *VD = IFD->getVarDecl();
|
|
|
|
assert(VD && "Expected a VarDecl in this IndirectFieldDecl!");
|
2017-09-22 04:25:05 +00:00
|
|
|
return getLVForNamespaceScopeDecl(VD, computation, IgnoreVarTypeLinkage);
|
2009-11-25 22:24:25 +00:00
|
|
|
}
|
2013-10-23 20:52:43 +00:00
|
|
|
assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!");
|
2009-11-25 22:24:25 +00:00
|
|
|
|
2019-04-26 01:51:08 +00:00
|
|
|
// FIXME: This gives internal linkage to names that should have no linkage
|
|
|
|
// (those not covered by [basic.link]p6).
|
2011-02-24 19:03:39 +00:00
|
|
|
if (D->isInAnonymousNamespace()) {
|
2015-11-09 17:53:06 +00:00
|
|
|
const auto *Var = dyn_cast<VarDecl>(D);
|
|
|
|
const auto *Func = dyn_cast<FunctionDecl>(D);
|
2017-09-22 22:21:44 +00:00
|
|
|
// FIXME: The check for extern "C" here is not justified by the standard
|
|
|
|
// wording, but we retain it from the pre-DR1113 model to avoid breaking
|
|
|
|
// code.
|
2017-07-07 20:04:28 +00:00
|
|
|
//
|
|
|
|
// C++11 [basic.link]p4:
|
|
|
|
// An unnamed namespace or a namespace declared directly or indirectly
|
|
|
|
// within an unnamed namespace has internal linkage.
|
2013-05-05 20:15:21 +00:00
|
|
|
if ((!Var || !isFirstInExternCContext(Var)) &&
|
|
|
|
(!Func || !isFirstInExternCContext(Func)))
|
2023-07-09 00:26:36 +00:00
|
|
|
return LinkageInfo::internal();
|
2011-02-24 19:03:39 +00:00
|
|
|
}
|
2010-10-28 04:18:25 +00:00
|
|
|
|
2010-10-22 21:05:15 +00:00
|
|
|
// Set up the defaults.
|
|
|
|
|
|
|
|
// 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.
|
2017-09-04 05:37:53 +00:00
|
|
|
LinkageInfo LV = getExternalLinkageFor(D);
|
2010-10-30 11:50:40 +00:00
|
|
|
|
2013-02-20 01:54:26 +00:00
|
|
|
if (!hasExplicitVisibilityAlready(computation)) {
|
2023-01-14 20:31:01 +00:00
|
|
|
if (std::optional<Visibility> Vis = getExplicitVisibility(D, computation)) {
|
2012-04-19 02:22:07 +00:00
|
|
|
LV.mergeVisibility(*Vis, true);
|
2012-04-16 18:46:26 +00:00
|
|
|
} else {
|
|
|
|
// If we're declared in a namespace with a visibility attribute,
|
2013-02-16 00:17:33 +00:00
|
|
|
// use that namespace's visibility, and it still counts as explicit.
|
2012-04-16 18:46:26 +00:00
|
|
|
for (const DeclContext *DC = D->getDeclContext();
|
|
|
|
!isa<TranslationUnitDecl>(DC);
|
|
|
|
DC = DC->getParent()) {
|
2015-11-09 17:53:06 +00:00
|
|
|
const auto *ND = dyn_cast<NamespaceDecl>(DC);
|
2012-04-16 18:46:26 +00:00
|
|
|
if (!ND) continue;
|
2023-01-14 20:31:01 +00:00
|
|
|
if (std::optional<Visibility> Vis =
|
|
|
|
getExplicitVisibility(ND, computation)) {
|
2012-04-19 02:22:07 +00:00
|
|
|
LV.mergeVisibility(*Vis, true);
|
2012-04-16 18:46:26 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-16 00:17:33 +00:00
|
|
|
// Add in global settings if the above didn't give us direct visibility.
|
2013-02-27 02:56:45 +00:00
|
|
|
if (!LV.isVisibilityExplicit()) {
|
2013-02-19 01:57:35 +00:00
|
|
|
// Use global type/value visibility as appropriate.
|
2017-09-22 02:22:32 +00:00
|
|
|
Visibility globalVisibility =
|
|
|
|
computation.isValueVisibility()
|
|
|
|
? Context.getLangOpts().getValueVisibilityMode()
|
|
|
|
: Context.getLangOpts().getTypeVisibilityMode();
|
2013-02-19 01:57:35 +00:00
|
|
|
LV.mergeVisibility(globalVisibility, /*explicit*/ false);
|
2013-02-16 00:17:33 +00:00
|
|
|
|
|
|
|
// If we're paying attention to global visibility, apply
|
|
|
|
// -finline-visibility-hidden if this is an inline method.
|
|
|
|
if (useInlineVisibilityHidden(D))
|
2018-10-10 21:59:56 +00:00
|
|
|
LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false);
|
2013-02-16 00:17:33 +00:00
|
|
|
}
|
2012-07-13 14:25:36 +00:00
|
|
|
}
|
2012-04-19 02:55:01 +00:00
|
|
|
|
2009-11-25 22:24:25 +00:00
|
|
|
// C++ [basic.link]p4:
|
2010-10-22 21:05:15 +00:00
|
|
|
|
2019-04-26 01:51:08 +00:00
|
|
|
// A name having namespace scope that has not been given internal linkage
|
|
|
|
// above and that is the name of
|
|
|
|
// [...bullets...]
|
|
|
|
// has its linkage determined as follows:
|
|
|
|
// - if the enclosing namespace has internal linkage, the name has
|
|
|
|
// internal linkage; [handled above]
|
|
|
|
// - otherwise, if the declaration of the name is attached to a named
|
|
|
|
// module and is not exported, the name has module linkage;
|
|
|
|
// - otherwise, the name has external linkage.
|
|
|
|
// LV is currently set up to handle the last two bullets.
|
2009-11-25 22:24:25 +00:00
|
|
|
//
|
2019-04-26 01:51:08 +00:00
|
|
|
// The bullets are:
|
|
|
|
|
|
|
|
// - a variable; or
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *Var = dyn_cast<VarDecl>(D)) {
|
2010-10-29 22:22:43 +00:00
|
|
|
// GCC applies the following optimization to variables and static
|
|
|
|
// data members, but not to functions:
|
|
|
|
//
|
2010-10-22 21:05:15 +00:00
|
|
|
// Modify the variable's LV by the LV of its type unless this is
|
|
|
|
// C or extern "C". This follows from [basic.link]p9:
|
|
|
|
// A type without linkage shall not be used as the type of a
|
|
|
|
// variable or function with external linkage unless
|
|
|
|
// - the entity has C language linkage, or
|
|
|
|
// - the entity is declared within an unnamed namespace, or
|
|
|
|
// - the entity is not used or is defined in the same
|
|
|
|
// translation unit.
|
|
|
|
// and [basic.link]p10:
|
|
|
|
// ...the types specified by all declarations referring to a
|
|
|
|
// given variable or function shall be identical...
|
|
|
|
// C does not have an equivalent rule.
|
|
|
|
//
|
2010-10-26 04:59:26 +00:00
|
|
|
// Ignore this if we've got an explicit attribute; the user
|
|
|
|
// probably knows what they're doing.
|
|
|
|
//
|
2010-10-22 21:05:15 +00:00
|
|
|
// Note that we don't want to make the variable non-external
|
|
|
|
// because of this, but unique-external linkage suits us.
|
2022-01-14 22:21:46 +00:00
|
|
|
|
2017-09-22 04:25:05 +00:00
|
|
|
if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var) &&
|
|
|
|
!IgnoreVarTypeLinkage) {
|
2013-05-29 04:55:30 +00:00
|
|
|
LinkageInfo TypeLV = getLVForType(*Var->getType(), computation);
|
2017-09-20 07:22:00 +00:00
|
|
|
if (!isExternallyVisible(TypeLV.getLinkage()))
|
2010-10-30 11:50:40 +00:00
|
|
|
return LinkageInfo::uniqueExternal();
|
2013-02-27 02:56:45 +00:00
|
|
|
if (!LV.isVisibilityExplicit())
|
2013-02-16 00:17:33 +00:00
|
|
|
LV.mergeVisibility(TypeLV);
|
2010-10-29 22:22:43 +00:00
|
|
|
}
|
|
|
|
|
2021-01-04 22:17:45 +00:00
|
|
|
if (Var->getStorageClass() == SC_PrivateExtern)
|
2012-04-19 02:22:07 +00:00
|
|
|
LV.mergeVisibility(HiddenVisibility, true);
|
2010-11-02 18:38:13 +00:00
|
|
|
|
2012-11-12 04:10:23 +00:00
|
|
|
// Note that Sema::MergeVarDecl already takes care of implementing
|
|
|
|
// C99 6.2.2p4 and propagating the visibility attribute, so we don't have
|
|
|
|
// to do it here.
|
2009-11-25 22:24:25 +00:00
|
|
|
|
2014-07-02 23:08:34 +00:00
|
|
|
// As per function and class template specializations (below),
|
|
|
|
// consider LV for the template and template arguments. We're at file
|
|
|
|
// scope, so we do not need to worry about nested specializations.
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(Var)) {
|
2014-07-02 23:08:34 +00:00
|
|
|
mergeTemplateLV(LV, spec, computation);
|
|
|
|
}
|
|
|
|
|
2019-04-26 01:51:08 +00:00
|
|
|
// - a function; or
|
2015-11-09 17:53:06 +00:00
|
|
|
} else if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
|
2010-10-28 07:07:52 +00:00
|
|
|
// In theory, we can modify the function's LV by the LV of its
|
|
|
|
// type unless it has C linkage (see comment above about variables
|
|
|
|
// for justification). In practice, GCC doesn't do this, so it's
|
|
|
|
// just too painful to make work.
|
2010-10-22 21:05:15 +00:00
|
|
|
|
2021-01-04 22:17:45 +00:00
|
|
|
if (Function->getStorageClass() == SC_PrivateExtern)
|
2012-04-19 02:22:07 +00:00
|
|
|
LV.mergeVisibility(HiddenVisibility, true);
|
2010-11-02 18:38:13 +00:00
|
|
|
|
2022-10-17 20:53:31 +00:00
|
|
|
// OpenMP target declare device functions are not callable from the host so
|
|
|
|
// they should not be exported from the device image. This applies to all
|
|
|
|
// functions as the host-callable kernel functions are emitted at codegen.
|
2023-07-06 09:28:24 +00:00
|
|
|
if (Context.getLangOpts().OpenMP &&
|
|
|
|
Context.getLangOpts().OpenMPIsTargetDevice &&
|
2022-10-17 20:53:31 +00:00
|
|
|
((Context.getTargetInfo().getTriple().isAMDGPU() ||
|
|
|
|
Context.getTargetInfo().getTriple().isNVPTX()) ||
|
|
|
|
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Function)))
|
|
|
|
LV.mergeVisibility(HiddenVisibility, /*newExplicit=*/false);
|
|
|
|
|
2012-11-21 02:47:19 +00:00
|
|
|
// Note that Sema::MergeCompatibleFunctionDecls already takes care of
|
|
|
|
// merging storage classes and visibility attributes, so we don't have to
|
|
|
|
// look at previous decls in here.
|
2009-11-25 22:24:25 +00:00
|
|
|
|
2011-02-10 06:50:24 +00:00
|
|
|
// In C++, then if the type of the function uses a type with
|
|
|
|
// unique-external linkage, it's not legally usable from outside
|
|
|
|
// this translation unit. However, we should use the C linkage
|
|
|
|
// rules instead for extern "C" declarations.
|
2018-01-03 02:34:35 +00:00
|
|
|
if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Function)) {
|
2017-09-22 04:25:05 +00:00
|
|
|
// Only look at the type-as-written. Otherwise, deducing the return type
|
|
|
|
// of a function could change its linkage.
|
2013-05-12 23:17:59 +00:00
|
|
|
QualType TypeAsWritten = Function->getType();
|
|
|
|
if (TypeSourceInfo *TSI = Function->getTypeSourceInfo())
|
|
|
|
TypeAsWritten = TSI->getType();
|
2017-09-20 07:22:00 +00:00
|
|
|
if (!isExternallyVisible(TypeAsWritten->getLinkage()))
|
2013-05-12 23:17:59 +00:00
|
|
|
return LinkageInfo::uniqueExternal();
|
|
|
|
}
|
2011-02-10 06:50:24 +00:00
|
|
|
|
2013-02-21 23:42:58 +00:00
|
|
|
// Consider LV from the template and the template arguments.
|
|
|
|
// We're at file scope, so we do not need to worry about nested
|
|
|
|
// specializations.
|
2011-06-27 23:06:04 +00:00
|
|
|
if (FunctionTemplateSpecializationInfo *specInfo
|
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
|
|
|
= Function->getTemplateSpecializationInfo()) {
|
2013-05-29 04:55:30 +00:00
|
|
|
mergeTemplateLV(LV, Function, specInfo, computation);
|
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
|
|
|
}
|
|
|
|
|
2009-11-25 22:24:25 +00:00
|
|
|
// - 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
|
2015-11-09 17:53:06 +00:00
|
|
|
} else if (const auto *Tag = dyn_cast<TagDecl>(D)) {
|
2010-10-22 21:05:15 +00:00
|
|
|
// Unnamed tags have no linkage.
|
2013-03-09 00:54:27 +00:00
|
|
|
if (!Tag->hasNameForLinkage())
|
2010-10-30 11:50:40 +00:00
|
|
|
return LinkageInfo::none();
|
2010-10-22 21:05:15 +00:00
|
|
|
|
|
|
|
// If this is a class template specialization, consider the
|
2013-02-21 23:42:58 +00:00
|
|
|
// linkage of the template and template arguments. We're at file
|
|
|
|
// scope, so we do not need to worry about nested specializations.
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
|
2013-02-16 00:17:33 +00:00
|
|
|
mergeTemplateLV(LV, spec, computation);
|
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
|
|
|
}
|
2009-11-25 22:24:25 +00:00
|
|
|
|
2019-04-26 01:51:08 +00:00
|
|
|
// FIXME: This is not part of the C++ standard any more.
|
|
|
|
// - an enumerator belonging to an enumeration with external linkage; or
|
2010-10-22 21:05:15 +00:00
|
|
|
} else if (isa<EnumConstantDecl>(D)) {
|
2012-04-21 23:28:21 +00:00
|
|
|
LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()),
|
2013-02-16 00:17:33 +00:00
|
|
|
computation);
|
2013-05-27 14:14:42 +00:00
|
|
|
if (!isExternalFormalLinkage(EnumLV.getLinkage()))
|
2010-10-30 11:50:40 +00:00
|
|
|
return LinkageInfo::none();
|
|
|
|
LV.merge(EnumLV);
|
2009-11-25 22:24:25 +00:00
|
|
|
|
2019-04-26 01:51:08 +00:00
|
|
|
// - a template
|
2015-11-09 17:53:06 +00:00
|
|
|
} else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
|
2013-02-20 01:54:26 +00:00
|
|
|
bool considerVisibility = !hasExplicitVisibilityAlready(computation);
|
2013-02-16 00:17:33 +00:00
|
|
|
LinkageInfo tempLV =
|
2013-05-29 04:55:30 +00:00
|
|
|
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
|
2013-02-16 00:17:33 +00:00
|
|
|
LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
|
|
|
|
|
2019-04-26 01:51:08 +00:00
|
|
|
// An unnamed namespace or a namespace declared directly or indirectly
|
|
|
|
// within an unnamed namespace has internal linkage. All other namespaces
|
|
|
|
// have external linkage.
|
2017-07-07 20:04:28 +00:00
|
|
|
//
|
|
|
|
// We handled names in anonymous namespaces above.
|
|
|
|
} else if (isa<NamespaceDecl>(D)) {
|
2010-10-22 21:05:15 +00:00
|
|
|
return LV;
|
|
|
|
|
|
|
|
// By extension, we assign external linkage to Objective-C
|
|
|
|
// interfaces.
|
|
|
|
} else if (isa<ObjCInterfaceDecl>(D)) {
|
|
|
|
// fallout
|
|
|
|
|
[modules] Simplify and generalize the existing rule for finding hidden
declarations in redeclaration lookup. A declaration is now visible to
lookup if:
* It is visible (not in a module, or in an imported module), or
* We're doing redeclaration lookup and it's externally-visible, or
* We're doing typo correction and looking for unimported decls.
We now support multiple modules having different internal-linkage or no-linkage
definitions of the same name for all entities, not just for functions,
variables, and some typedefs. As previously, if multiple such entities are
visible, any attempt to use them will result in an ambiguity error.
This patch fixes the linkage calculation for a number of entities where we
previously didn't need to get it right (using-declarations, namespace aliases,
and so on). It also classifies enumerators as always having no linkage, which
is a slight deviation from the C++ standard's definition, but not an observable
change outside modules (this change is being discussed on the -core reflector
currently).
This also removes the prior special case for tag lookup, which made some cases
of this work, but also led to bizarre, bogus "must use 'struct' to refer to type
'Foo' in this scope" diagnostics in C++.
llvm-svn: 252960
2015-11-12 22:19:45 +00:00
|
|
|
} else if (auto *TD = dyn_cast<TypedefNameDecl>(D)) {
|
|
|
|
// A typedef declaration has linkage if it gives a type a name for
|
|
|
|
// linkage purposes.
|
|
|
|
if (!TD->getAnonDeclWithTypedefName(/*AnyRedecl*/true))
|
|
|
|
return LinkageInfo::none();
|
|
|
|
|
Rework how UuidAttr, CXXUuidofExpr, and GUID template arguments and constants are represented.
Summary:
Previously, we treated CXXUuidofExpr as quite a special case: it was the
only kind of expression that could be a canonical template argument, it
could be a constant lvalue base object, and so on. In addition, we
represented the UUID value as a string, whose source form we did not
preserve faithfully, and that we partially parsed in multiple different
places.
With this patch, we create an MSGuidDecl object to represent the
implicit object of type 'struct _GUID' created by a UuidAttr. Each
UuidAttr holds a pointer to its 'struct _GUID' and its original
(as-written) UUID string. A non-value-dependent CXXUuidofExpr behaves
like a DeclRefExpr denoting that MSGuidDecl object. We cache an APValue
representation of the GUID on the MSGuidDecl and use it from constant
evaluation where needed.
This allows removing a lot of the special-case logic to handle these
expressions. Unfortunately, many parts of Clang assume there are only
a couple of interesting kinds of ValueDecl, so the total amount of
special-case logic is not really reduced very much.
This fixes a few bugs and issues:
* PR38490: we now support reading from GUID objects returned from
__uuidof during constant evaluation.
* Our Itanium mangling for a non-instantiation-dependent template
argument involving __uuidof no longer depends on which CXXUuidofExpr
template argument we happened to see first.
* We now predeclare ::_GUID, and permit use of __uuidof without
any header inclusion, better matching MSVC's behavior. We do not
predefine ::__s_GUID, though; that seems like a step too far.
* Our IR representation for GUID constants now uses the correct IR type
wherever possible. We will still fall back to using the
{i32, i16, i16, [8 x i8]}
layout if a definition of struct _GUID is not available. This is not
ideal: in principle the two layouts could have different padding.
Reviewers: rnk, jdoerfert
Subscribers: arphaman, cfe-commits, aeubanks
Tags: #clang
Differential Revision: https://reviews.llvm.org/D78171
2020-04-12 05:15:29 +00:00
|
|
|
} else if (isa<MSGuidDecl>(D)) {
|
|
|
|
// A GUID behaves like an inline variable with external linkage. Fall
|
|
|
|
// through.
|
|
|
|
|
2010-10-22 21:05:15 +00:00
|
|
|
// Everything not covered here has no linkage.
|
|
|
|
} else {
|
2010-10-30 11:50:40 +00:00
|
|
|
return LinkageInfo::none();
|
2010-10-22 21:05:15 +00:00
|
|
|
}
|
|
|
|
|
2017-10-03 01:58:15 +00:00
|
|
|
// If we ended up with non-externally-visible linkage, visibility should
|
2010-10-22 21:05:15 +00:00
|
|
|
// always be default.
|
2017-10-03 01:58:15 +00:00
|
|
|
if (!isExternallyVisible(LV.getLinkage()))
|
2013-02-27 02:56:45 +00:00
|
|
|
return LinkageInfo(LV.getLinkage(), DefaultVisibility, false);
|
2010-10-22 21:05:15 +00:00
|
|
|
|
|
|
|
return LV;
|
2009-11-25 22:24:25 +00:00
|
|
|
}
|
|
|
|
|
2017-08-09 04:02:49 +00:00
|
|
|
LinkageInfo
|
|
|
|
LinkageComputer::getLVForClassMember(const NamedDecl *D,
|
2017-09-22 04:25:05 +00:00
|
|
|
LVComputationKind computation,
|
|
|
|
bool IgnoreVarTypeLinkage) {
|
2010-10-22 21:05:15 +00:00
|
|
|
// Only certain class members have linkage. Note that fields don't
|
|
|
|
// really have linkage, but it's convenient to say they do for the
|
|
|
|
// purposes of calculating linkage of pointer-to-data-member
|
|
|
|
// template arguments.
|
2014-01-08 01:51:59 +00:00
|
|
|
//
|
|
|
|
// Templates also don't officially have linkage, but since we ignore
|
|
|
|
// the C++ standard and look at template arguments when determining
|
|
|
|
// linkage and visibility of a template specialization, we might hit
|
|
|
|
// a template template argument that way. If we do, we need to
|
|
|
|
// consider its linkage.
|
2010-08-13 08:35:10 +00:00
|
|
|
if (!(isa<CXXMethodDecl>(D) ||
|
|
|
|
isa<VarDecl>(D) ||
|
2010-10-22 21:05:15 +00:00
|
|
|
isa<FieldDecl>(D) ||
|
2013-10-23 20:52:43 +00:00
|
|
|
isa<IndirectFieldDecl>(D) ||
|
2014-01-08 01:51:59 +00:00
|
|
|
isa<TagDecl>(D) ||
|
|
|
|
isa<TemplateDecl>(D)))
|
2010-10-30 11:50:40 +00:00
|
|
|
return LinkageInfo::none();
|
2010-08-13 08:35:10 +00:00
|
|
|
|
2010-11-02 01:45:15 +00:00
|
|
|
LinkageInfo LV;
|
|
|
|
|
|
|
|
// If we have an explicit visibility attribute, merge that in.
|
2013-02-20 01:54:26 +00:00
|
|
|
if (!hasExplicitVisibilityAlready(computation)) {
|
2023-01-14 20:31:01 +00:00
|
|
|
if (std::optional<Visibility> Vis = getExplicitVisibility(D, computation))
|
2011-03-26 12:10:19 +00:00
|
|
|
LV.mergeVisibility(*Vis, true);
|
2012-07-13 14:25:36 +00:00
|
|
|
// If we're paying attention to global visibility, apply
|
|
|
|
// -finline-visibility-hidden if this is an inline method.
|
|
|
|
//
|
|
|
|
// Note that we do this before merging information about
|
|
|
|
// the class visibility.
|
2013-02-27 02:56:45 +00:00
|
|
|
if (!LV.isVisibilityExplicit() && useInlineVisibilityHidden(D))
|
2018-10-10 21:59:56 +00:00
|
|
|
LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false);
|
2012-04-16 18:25:01 +00:00
|
|
|
}
|
2012-04-19 05:50:08 +00:00
|
|
|
|
|
|
|
// If this class member has an explicit visibility attribute, the only
|
|
|
|
// thing that can change its visibility is the template arguments, so
|
2012-07-23 08:59:39 +00:00
|
|
|
// only look for them when processing the class.
|
2013-02-20 01:54:26 +00:00
|
|
|
LVComputationKind classComputation = computation;
|
2013-02-27 02:56:45 +00:00
|
|
|
if (LV.isVisibilityExplicit())
|
2013-02-20 01:54:26 +00:00
|
|
|
classComputation = withExplicitVisibilityAlready(computation);
|
2010-11-02 01:45:15 +00:00
|
|
|
|
2013-02-21 23:42:58 +00:00
|
|
|
LinkageInfo classLV =
|
|
|
|
getLVForDecl(cast<RecordDecl>(D->getDeclContext()), classComputation);
|
2017-09-23 04:02:17 +00:00
|
|
|
// The member has the same linkage as the class. If that's not externally
|
|
|
|
// visible, we don't need to compute anything about the linkage.
|
|
|
|
// FIXME: If we're only computing linkage, can we bail out here?
|
2013-05-28 02:22:10 +00:00
|
|
|
if (!isExternallyVisible(classLV.getLinkage()))
|
2017-09-23 04:02:17 +00:00
|
|
|
return classLV;
|
2013-05-28 02:22:10 +00:00
|
|
|
|
|
|
|
|
2013-02-21 23:42:58 +00:00
|
|
|
// Otherwise, don't merge in classLV yet, because in certain cases
|
|
|
|
// we need to completely ignore the visibility from it.
|
|
|
|
|
|
|
|
// Specifically, if this decl exists and has an explicit attribute.
|
2014-05-12 05:36:57 +00:00
|
|
|
const NamedDecl *explicitSpecSuppressor = nullptr;
|
2013-02-21 23:42:58 +00:00
|
|
|
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
|
2017-09-22 04:25:05 +00:00
|
|
|
// Only look at the type-as-written. Otherwise, deducing the return type
|
|
|
|
// of a function could change its linkage.
|
|
|
|
QualType TypeAsWritten = MD->getType();
|
|
|
|
if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
|
|
|
|
TypeAsWritten = TSI->getType();
|
|
|
|
if (!isExternallyVisible(TypeAsWritten->getLinkage()))
|
|
|
|
return LinkageInfo::uniqueExternal();
|
|
|
|
|
2010-10-22 21:05:15 +00:00
|
|
|
// If this is a method template specialization, use the linkage for
|
|
|
|
// the template parameters and arguments.
|
2011-06-27 23:06:04 +00:00
|
|
|
if (FunctionTemplateSpecializationInfo *spec
|
2010-08-13 08:35:10 +00:00
|
|
|
= MD->getTemplateSpecializationInfo()) {
|
2013-05-29 04:55:30 +00:00
|
|
|
mergeTemplateLV(LV, MD, spec, computation);
|
2013-02-21 23:42:58 +00:00
|
|
|
if (spec->isExplicitSpecialization()) {
|
|
|
|
explicitSpecSuppressor = MD;
|
|
|
|
} else if (isExplicitMemberSpecialization(spec->getTemplate())) {
|
|
|
|
explicitSpecSuppressor = spec->getTemplate()->getTemplatedDecl();
|
|
|
|
}
|
|
|
|
} else if (isExplicitMemberSpecialization(MD)) {
|
|
|
|
explicitSpecSuppressor = MD;
|
2010-11-01 01:29:57 +00:00
|
|
|
}
|
2010-10-22 21:05:15 +00:00
|
|
|
|
2022-12-28 19:19:27 +00:00
|
|
|
// OpenMP target declare device functions are not callable from the host so
|
|
|
|
// they should not be exported from the device image. This applies to all
|
|
|
|
// functions as the host-callable kernel functions are emitted at codegen.
|
|
|
|
ASTContext &Context = D->getASTContext();
|
2023-07-06 09:28:24 +00:00
|
|
|
if (Context.getLangOpts().OpenMP &&
|
|
|
|
Context.getLangOpts().OpenMPIsTargetDevice &&
|
2022-12-28 19:19:27 +00:00
|
|
|
((Context.getTargetInfo().getTriple().isAMDGPU() ||
|
|
|
|
Context.getTargetInfo().getTriple().isNVPTX()) ||
|
|
|
|
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(MD)))
|
|
|
|
LV.mergeVisibility(HiddenVisibility, /*newExplicit=*/false);
|
|
|
|
|
2015-11-09 17:53:06 +00:00
|
|
|
} else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
|
|
|
|
if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
|
2013-02-16 00:17:33 +00:00
|
|
|
mergeTemplateLV(LV, spec, computation);
|
2013-02-21 23:42:58 +00:00
|
|
|
if (spec->isExplicitSpecialization()) {
|
|
|
|
explicitSpecSuppressor = spec;
|
|
|
|
} else {
|
|
|
|
const ClassTemplateDecl *temp = spec->getSpecializedTemplate();
|
|
|
|
if (isExplicitMemberSpecialization(temp)) {
|
|
|
|
explicitSpecSuppressor = temp->getTemplatedDecl();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (isExplicitMemberSpecialization(RD)) {
|
|
|
|
explicitSpecSuppressor = RD;
|
2010-10-29 22:22:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Static data members.
|
2015-11-09 17:53:06 +00:00
|
|
|
} else if (const auto *VD = dyn_cast<VarDecl>(D)) {
|
|
|
|
if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(VD))
|
2014-07-02 23:08:34 +00:00
|
|
|
mergeTemplateLV(LV, spec, computation);
|
|
|
|
|
2010-10-30 09:18:49 +00:00
|
|
|
// Modify the variable's linkage by its type, but ignore the
|
|
|
|
// type's visibility unless it's a definition.
|
2017-09-22 04:25:05 +00:00
|
|
|
if (!IgnoreVarTypeLinkage) {
|
|
|
|
LinkageInfo typeLV = getLVForType(*VD->getType(), computation);
|
|
|
|
// FIXME: If the type's linkage is not externally visible, we can
|
|
|
|
// give this static data member UniqueExternalLinkage.
|
|
|
|
if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit())
|
|
|
|
LV.mergeVisibility(typeLV);
|
|
|
|
LV.mergeExternalVisibility(typeLV);
|
|
|
|
}
|
2013-02-21 23:42:58 +00:00
|
|
|
|
|
|
|
if (isExplicitMemberSpecialization(VD)) {
|
|
|
|
explicitSpecSuppressor = VD;
|
|
|
|
}
|
2013-02-16 00:17:33 +00:00
|
|
|
|
|
|
|
// Template members.
|
2015-11-09 17:53:06 +00:00
|
|
|
} else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
|
2013-02-16 00:17:33 +00:00
|
|
|
bool considerVisibility =
|
2013-02-27 02:56:45 +00:00
|
|
|
(!LV.isVisibilityExplicit() &&
|
|
|
|
!classLV.isVisibilityExplicit() &&
|
2013-02-20 01:54:26 +00:00
|
|
|
!hasExplicitVisibilityAlready(computation));
|
2013-02-16 00:17:33 +00:00
|
|
|
LinkageInfo tempLV =
|
2013-05-29 04:55:30 +00:00
|
|
|
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
|
2013-02-16 00:17:33 +00:00
|
|
|
LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
|
2013-02-21 23:42:58 +00:00
|
|
|
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *redeclTemp = dyn_cast<RedeclarableTemplateDecl>(temp)) {
|
2013-02-21 23:42:58 +00:00
|
|
|
if (isExplicitMemberSpecialization(redeclTemp)) {
|
|
|
|
explicitSpecSuppressor = temp->getTemplatedDecl();
|
|
|
|
}
|
|
|
|
}
|
2010-10-29 22:22:43 +00:00
|
|
|
}
|
|
|
|
|
2013-02-21 23:42:58 +00:00
|
|
|
// We should never be looking for an attribute directly on a template.
|
|
|
|
assert(!explicitSpecSuppressor || !isa<TemplateDecl>(explicitSpecSuppressor));
|
|
|
|
|
|
|
|
// If this member is an explicit member specialization, and it has
|
|
|
|
// an explicit attribute, ignore visibility from the parent.
|
|
|
|
bool considerClassVisibility = true;
|
|
|
|
if (explicitSpecSuppressor &&
|
2013-02-27 02:56:45 +00:00
|
|
|
// optimization: hasDVA() is true only with explicit visibility.
|
|
|
|
LV.isVisibilityExplicit() &&
|
|
|
|
classLV.getVisibility() != DefaultVisibility &&
|
2013-02-21 23:42:58 +00:00
|
|
|
hasDirectVisibilityAttribute(explicitSpecSuppressor, computation)) {
|
|
|
|
considerClassVisibility = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, merge in information from the class.
|
|
|
|
LV.mergeMaybeWithVisibility(classLV, considerClassVisibility);
|
2010-10-22 21:05:15 +00:00
|
|
|
return LV;
|
2010-08-13 08:35:10 +00:00
|
|
|
}
|
|
|
|
|
2017-11-13 23:01:27 +00:00
|
|
|
void NamedDecl::anchor() {}
|
2011-12-20 02:48:34 +00:00
|
|
|
|
2013-03-14 03:07:35 +00:00
|
|
|
bool NamedDecl::isLinkageValid() const {
|
2013-05-25 17:16:20 +00:00
|
|
|
if (!hasCachedLinkage())
|
2013-03-14 03:07:35 +00:00
|
|
|
return true;
|
2011-02-19 02:53:41 +00:00
|
|
|
|
2017-09-22 02:22:32 +00:00
|
|
|
Linkage L = LinkageComputer{}
|
|
|
|
.computeLVForDecl(this, LVComputationKind::forLinkageOnly())
|
|
|
|
.getLinkage();
|
2017-08-09 04:02:49 +00:00
|
|
|
return L == getCachedLinkage();
|
2011-02-08 19:01:05 +00:00
|
|
|
}
|
|
|
|
|
2023-06-22 12:18:38 +00:00
|
|
|
bool NamedDecl::isPlaceholderVar(const LangOptions &LangOpts) const {
|
|
|
|
// [C++2c] [basic.scope.scope]/p5
|
|
|
|
// A declaration is name-independent if its name is _ and it declares
|
|
|
|
// - a variable with automatic storage duration,
|
|
|
|
// - a structured binding not inhabiting a namespace scope,
|
|
|
|
// - the variable introduced by an init-capture
|
|
|
|
// - or a non-static data member.
|
|
|
|
|
|
|
|
if (!LangOpts.CPlusPlus || !getIdentifier() ||
|
|
|
|
!getIdentifier()->isPlaceholder())
|
|
|
|
return false;
|
|
|
|
if (isa<FieldDecl>(this))
|
|
|
|
return true;
|
|
|
|
if (auto *IFD = dyn_cast<IndirectFieldDecl>(this)) {
|
|
|
|
if (!getDeclContext()->isFunctionOrMethod() &&
|
|
|
|
!getDeclContext()->isRecord())
|
|
|
|
return false;
|
|
|
|
VarDecl *VD = IFD->getVarDecl();
|
|
|
|
return !VD || VD->getStorageDuration() == SD_Automatic;
|
|
|
|
}
|
|
|
|
// and it declares a variable with automatic storage duration
|
|
|
|
if (const auto *VD = dyn_cast<VarDecl>(this)) {
|
|
|
|
if (isa<ParmVarDecl>(VD))
|
|
|
|
return false;
|
|
|
|
if (VD->isInitCapture())
|
|
|
|
return true;
|
|
|
|
return VD->getStorageDuration() == StorageDuration::SD_Automatic;
|
|
|
|
}
|
|
|
|
if (const auto *BD = dyn_cast<BindingDecl>(this);
|
|
|
|
BD && getDeclContext()->isFunctionOrMethod()) {
|
|
|
|
VarDecl *VD = BD->getHoldingVar();
|
|
|
|
return !VD || VD->getStorageDuration() == StorageDuration::SD_Automatic;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-12-09 08:26:27 +00:00
|
|
|
ReservedIdentifierStatus
|
|
|
|
NamedDecl::isReserved(const LangOptions &LangOpts) const {
|
|
|
|
const IdentifierInfo *II = getIdentifier();
|
|
|
|
|
2021-06-15 14:58:55 +00:00
|
|
|
// This triggers at least for CXXLiteralIdentifiers, which we already checked
|
|
|
|
// at lexing time.
|
2020-12-09 08:26:27 +00:00
|
|
|
if (!II)
|
|
|
|
return ReservedIdentifierStatus::NotReserved;
|
|
|
|
|
|
|
|
ReservedIdentifierStatus Status = II->isReserved(LangOpts);
|
2021-10-06 21:11:32 +00:00
|
|
|
if (isReservedAtGlobalScope(Status) && !isReservedInAllContexts(Status)) {
|
2021-10-06 22:11:12 +00:00
|
|
|
// This name is only reserved at global scope. Check if this declaration
|
|
|
|
// conflicts with a global scope declaration.
|
2020-12-09 08:26:27 +00:00
|
|
|
if (isa<ParmVarDecl>(this) || isTemplateParameter())
|
|
|
|
return ReservedIdentifierStatus::NotReserved;
|
2021-10-06 22:11:12 +00:00
|
|
|
|
|
|
|
// C++ [dcl.link]/7:
|
|
|
|
// Two declarations [conflict] if [...] one declares a function or
|
|
|
|
// variable with C language linkage, and the other declares [...] a
|
|
|
|
// variable that belongs to the global scope.
|
|
|
|
//
|
|
|
|
// Therefore names that are reserved at global scope are also reserved as
|
|
|
|
// names of variables and functions with C language linkage.
|
2020-12-09 08:26:27 +00:00
|
|
|
const DeclContext *DC = getDeclContext()->getRedeclContext();
|
2021-10-06 22:11:12 +00:00
|
|
|
if (DC->isTranslationUnit())
|
|
|
|
return Status;
|
|
|
|
if (auto *VD = dyn_cast<VarDecl>(this))
|
|
|
|
if (VD->isExternC())
|
|
|
|
return ReservedIdentifierStatus::StartsWithUnderscoreAndIsExternC;
|
|
|
|
if (auto *FD = dyn_cast<FunctionDecl>(this))
|
|
|
|
if (FD->isExternC())
|
|
|
|
return ReservedIdentifierStatus::StartsWithUnderscoreAndIsExternC;
|
|
|
|
return ReservedIdentifierStatus::NotReserved;
|
2020-12-09 08:26:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2014-09-09 23:10:54 +00:00
|
|
|
ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const {
|
|
|
|
StringRef name = getName();
|
|
|
|
if (name.empty()) return SFF_None;
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2014-09-09 23:10:54 +00:00
|
|
|
if (name.front() == 'C')
|
|
|
|
if (name == "CFStringCreateWithFormat" ||
|
|
|
|
name == "CFStringCreateWithFormatAndArguments" ||
|
|
|
|
name == "CFStringAppendFormat" ||
|
|
|
|
name == "CFStringAppendFormatAndArguments")
|
|
|
|
return SFF_CFString;
|
|
|
|
return SFF_None;
|
|
|
|
}
|
|
|
|
|
2013-05-13 00:12:11 +00:00
|
|
|
Linkage NamedDecl::getLinkageInternal() const {
|
2013-02-20 01:54:26 +00:00
|
|
|
// We don't care about visibility here, so ask for the cheapest
|
|
|
|
// possible visibility analysis.
|
2017-09-22 02:22:32 +00:00
|
|
|
return LinkageComputer{}
|
|
|
|
.getLVForDecl(this, LVComputationKind::forLinkageOnly())
|
|
|
|
.getLinkage();
|
2010-12-06 18:36:25 +00:00
|
|
|
}
|
|
|
|
|
2023-03-13 07:43:08 +00:00
|
|
|
/// Get the linkage from a semantic point of view. Entities in
|
|
|
|
/// anonymous namespaces are external (in c++98).
|
|
|
|
Linkage NamedDecl::getFormalLinkage() const {
|
|
|
|
Linkage InternalLinkage = getLinkageInternal();
|
|
|
|
|
|
|
|
// C++ [basic.link]p4.8:
|
|
|
|
// - if the declaration of the name is attached to a named module and is not
|
|
|
|
// exported
|
|
|
|
// the name has module linkage;
|
|
|
|
//
|
|
|
|
// [basic.namespace.general]/p2
|
|
|
|
// A namespace is never attached to a named module and never has a name with
|
|
|
|
// module linkage.
|
2023-11-02 16:57:29 +00:00
|
|
|
if (isInModulePurview(this) && InternalLinkage == Linkage::External &&
|
2023-03-13 07:43:08 +00:00
|
|
|
!isExportedFromModuleInterfaceUnit(
|
|
|
|
cast<NamedDecl>(this->getCanonicalDecl())) &&
|
|
|
|
!isa<NamespaceDecl>(this))
|
2023-11-02 16:57:29 +00:00
|
|
|
InternalLinkage = Linkage::Module;
|
2023-03-13 07:43:08 +00:00
|
|
|
|
|
|
|
return clang::getFormalLinkage(InternalLinkage);
|
|
|
|
}
|
|
|
|
|
2010-10-30 11:50:40 +00:00
|
|
|
LinkageInfo NamedDecl::getLinkageAndVisibility() const {
|
2017-08-09 04:02:49 +00:00
|
|
|
return LinkageComputer{}.getDeclLinkageAndVisibility(this);
|
2010-10-29 00:29:13 +00:00
|
|
|
}
|
2010-04-20 23:15:35 +00:00
|
|
|
|
2023-01-14 20:31:01 +00:00
|
|
|
static std::optional<Visibility>
|
2013-11-26 16:09:08 +00:00
|
|
|
getExplicitVisibilityAux(const NamedDecl *ND,
|
|
|
|
NamedDecl::ExplicitVisibilityKind kind,
|
|
|
|
bool IsMostRecent) {
|
|
|
|
assert(!IsMostRecent || ND == ND->getMostRecentDecl());
|
|
|
|
|
2013-02-26 19:33:14 +00:00
|
|
|
// Check the declaration itself first.
|
2023-01-14 20:31:01 +00:00
|
|
|
if (std::optional<Visibility> V = getVisibilityOf(ND, kind))
|
2013-02-26 19:33:14 +00:00
|
|
|
return V;
|
|
|
|
|
|
|
|
// If this is a member class of a specialization of a class template
|
|
|
|
// and the corresponding decl has explicit visibility, use that.
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
|
2013-02-26 19:33:14 +00:00
|
|
|
CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
|
|
|
|
if (InstantiatedFrom)
|
|
|
|
return getVisibilityOf(InstantiatedFrom, kind);
|
|
|
|
}
|
2012-05-16 02:10:38 +00:00
|
|
|
|
2013-02-26 19:33:14 +00:00
|
|
|
// If there wasn't explicit visibility there, and this is a
|
|
|
|
// specialization of a class template, check for visibility
|
|
|
|
// on the pattern.
|
2018-04-19 15:46:43 +00:00
|
|
|
if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
|
|
|
|
// Walk all the template decl till this point to see if there are
|
|
|
|
// explicit visibility attributes.
|
|
|
|
const auto *TD = spec->getSpecializedTemplate()->getTemplatedDecl();
|
|
|
|
while (TD != nullptr) {
|
|
|
|
auto Vis = getVisibilityOf(TD, kind);
|
2022-12-03 19:13:41 +00:00
|
|
|
if (Vis != std::nullopt)
|
2018-04-19 15:46:43 +00:00
|
|
|
return Vis;
|
|
|
|
TD = TD->getPreviousDecl();
|
|
|
|
}
|
2022-12-03 19:13:41 +00:00
|
|
|
return std::nullopt;
|
2018-04-19 15:46:43 +00:00
|
|
|
}
|
2013-02-26 19:33:14 +00:00
|
|
|
|
|
|
|
// Use the most recent declaration.
|
2013-12-08 01:13:22 +00:00
|
|
|
if (!IsMostRecent && !isa<NamespaceDecl>(ND)) {
|
2013-11-26 16:09:08 +00:00
|
|
|
const NamedDecl *MostRecent = ND->getMostRecentDecl();
|
|
|
|
if (MostRecent != ND)
|
|
|
|
return getExplicitVisibilityAux(MostRecent, kind, true);
|
|
|
|
}
|
2013-02-26 19:33:14 +00:00
|
|
|
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *Var = dyn_cast<VarDecl>(ND)) {
|
2012-05-16 02:10:38 +00:00
|
|
|
if (Var->isStaticDataMember()) {
|
|
|
|
VarDecl *InstantiatedFrom = Var->getInstantiatedFromStaticDataMember();
|
|
|
|
if (InstantiatedFrom)
|
2013-02-20 01:54:26 +00:00
|
|
|
return getVisibilityOf(InstantiatedFrom, kind);
|
2012-05-16 02:10:38 +00:00
|
|
|
}
|
2011-03-26 12:10:19 +00:00
|
|
|
|
2014-04-29 07:32:26 +00:00
|
|
|
if (const auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Var))
|
|
|
|
return getVisibilityOf(VTSD->getSpecializedTemplate()->getTemplatedDecl(),
|
|
|
|
kind);
|
|
|
|
|
2022-12-03 19:13:41 +00:00
|
|
|
return std::nullopt;
|
2012-05-16 02:10:38 +00:00
|
|
|
}
|
2013-02-26 19:33:14 +00:00
|
|
|
// Also handle function template specializations.
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *fn = dyn_cast<FunctionDecl>(ND)) {
|
2011-03-26 12:10:19 +00:00
|
|
|
// If the function is a specialization of a template with an
|
|
|
|
// explicit visibility attribute, use that.
|
|
|
|
if (FunctionTemplateSpecializationInfo *templateInfo
|
|
|
|
= fn->getTemplateSpecializationInfo())
|
2013-02-20 01:54:26 +00:00
|
|
|
return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl(),
|
|
|
|
kind);
|
2011-03-26 12:10:19 +00:00
|
|
|
|
2012-02-23 04:17:32 +00:00
|
|
|
// If the function is a member of a specialization of a class template
|
|
|
|
// and the corresponding decl has explicit visibility, use that.
|
|
|
|
FunctionDecl *InstantiatedFrom = fn->getInstantiatedFromMemberFunction();
|
|
|
|
if (InstantiatedFrom)
|
2013-02-20 01:54:26 +00:00
|
|
|
return getVisibilityOf(InstantiatedFrom, kind);
|
2012-02-23 04:17:32 +00:00
|
|
|
|
2022-12-03 19:13:41 +00:00
|
|
|
return std::nullopt;
|
2011-03-26 12:10:19 +00:00
|
|
|
}
|
|
|
|
|
2012-07-31 19:02:02 +00:00
|
|
|
// The visibility of a template is stored in the templated decl.
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *TD = dyn_cast<TemplateDecl>(ND))
|
2013-02-20 01:54:26 +00:00
|
|
|
return getVisibilityOf(TD->getTemplatedDecl(), kind);
|
2012-07-31 19:02:02 +00:00
|
|
|
|
2022-12-03 19:13:41 +00:00
|
|
|
return std::nullopt;
|
2011-03-26 12:10:19 +00:00
|
|
|
}
|
|
|
|
|
2023-01-14 20:31:01 +00:00
|
|
|
std::optional<Visibility>
|
2013-11-26 16:09:08 +00:00
|
|
|
NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
|
|
|
|
return getExplicitVisibilityAux(this, kind, false);
|
|
|
|
}
|
|
|
|
|
2017-08-09 04:02:49 +00:00
|
|
|
LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC,
|
|
|
|
Decl *ContextDecl,
|
|
|
|
LVComputationKind computation) {
|
2013-07-01 20:22:57 +00:00
|
|
|
// This lambda has its linkage/visibility determined by its owner.
|
2017-09-22 04:25:05 +00:00
|
|
|
const NamedDecl *Owner;
|
|
|
|
if (!ContextDecl)
|
|
|
|
Owner = dyn_cast<NamedDecl>(DC);
|
|
|
|
else if (isa<ParmVarDecl>(ContextDecl))
|
|
|
|
Owner =
|
|
|
|
dyn_cast<NamedDecl>(ContextDecl->getDeclContext()->getRedeclContext());
|
2022-10-24 19:20:36 +00:00
|
|
|
else if (isa<ImplicitConceptSpecializationDecl>(ContextDecl)) {
|
|
|
|
// Replace with the concept's owning decl, which is either a namespace or a
|
|
|
|
// TU, so this needs a dyn_cast.
|
|
|
|
Owner = dyn_cast<NamedDecl>(ContextDecl->getDeclContext());
|
|
|
|
} else {
|
2017-09-22 04:25:05 +00:00
|
|
|
Owner = cast<NamedDecl>(ContextDecl);
|
2022-10-24 19:20:36 +00:00
|
|
|
}
|
2017-09-22 04:25:05 +00:00
|
|
|
|
|
|
|
if (!Owner)
|
2017-09-22 04:33:20 +00:00
|
|
|
return LinkageInfo::none();
|
2017-09-22 04:25:05 +00:00
|
|
|
|
|
|
|
// If the owner has a deduced type, we need to skip querying the linkage and
|
|
|
|
// visibility of that type, because it might involve this closure type. The
|
|
|
|
// only effect of this is that we might give a lambda VisibleNoLinkage rather
|
|
|
|
// than NoLinkage when we don't strictly need to, which is benign.
|
|
|
|
auto *VD = dyn_cast<VarDecl>(Owner);
|
2017-09-22 04:33:20 +00:00
|
|
|
LinkageInfo OwnerLV =
|
2017-09-22 04:25:05 +00:00
|
|
|
VD && VD->getType()->getContainedDeducedType()
|
|
|
|
? computeLVForDecl(Owner, computation, /*IgnoreVarTypeLinkage*/true)
|
|
|
|
: getLVForDecl(Owner, computation);
|
|
|
|
|
2017-09-22 04:33:20 +00:00
|
|
|
// A lambda never formally has linkage. But if the owner is externally
|
|
|
|
// visible, then the lambda is too. We apply the same rules to blocks.
|
|
|
|
if (!isExternallyVisible(OwnerLV.getLinkage()))
|
|
|
|
return LinkageInfo::none();
|
2023-11-02 16:57:29 +00:00
|
|
|
return LinkageInfo(Linkage::VisibleNone, OwnerLV.getVisibility(),
|
2017-09-22 04:33:20 +00:00
|
|
|
OwnerLV.isVisibilityExplicit());
|
2013-07-01 20:22:57 +00:00
|
|
|
}
|
|
|
|
|
2017-08-09 04:02:49 +00:00
|
|
|
LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
|
|
|
|
LVComputationKind computation) {
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
|
2013-02-16 00:17:33 +00:00
|
|
|
if (Function->isInAnonymousNamespace() &&
|
2018-01-03 02:34:35 +00:00
|
|
|
!isFirstInExternCContext(Function))
|
2023-07-09 00:26:36 +00:00
|
|
|
return LinkageInfo::internal();
|
2013-02-16 00:17:33 +00:00
|
|
|
|
|
|
|
// This is a "void f();" which got merged with a file static.
|
2021-01-04 22:17:45 +00:00
|
|
|
if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
|
2023-07-09 00:26:36 +00:00
|
|
|
return LinkageInfo::internal();
|
2013-02-16 00:17:33 +00:00
|
|
|
|
|
|
|
LinkageInfo LV;
|
2013-02-20 01:54:26 +00:00
|
|
|
if (!hasExplicitVisibilityAlready(computation)) {
|
2023-01-14 20:31:01 +00:00
|
|
|
if (std::optional<Visibility> Vis =
|
2013-02-20 22:23:23 +00:00
|
|
|
getExplicitVisibility(Function, computation))
|
2013-02-16 00:17:33 +00:00
|
|
|
LV.mergeVisibility(*Vis, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Note that Sema::MergeCompatibleFunctionDecls already takes care of
|
|
|
|
// merging storage classes and visibility attributes, so we don't have to
|
|
|
|
// look at previous decls in here.
|
|
|
|
|
|
|
|
return LV;
|
|
|
|
}
|
|
|
|
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *Var = dyn_cast<VarDecl>(D)) {
|
2013-04-03 19:27:57 +00:00
|
|
|
if (Var->hasExternalStorage()) {
|
2018-01-03 02:34:35 +00:00
|
|
|
if (Var->isInAnonymousNamespace() && !isFirstInExternCContext(Var))
|
2023-07-09 00:26:36 +00:00
|
|
|
return LinkageInfo::internal();
|
2013-02-16 00:17:33 +00:00
|
|
|
|
|
|
|
LinkageInfo LV;
|
2021-01-04 22:17:45 +00:00
|
|
|
if (Var->getStorageClass() == SC_PrivateExtern)
|
2013-02-16 00:17:33 +00:00
|
|
|
LV.mergeVisibility(HiddenVisibility, true);
|
2013-02-20 01:54:26 +00:00
|
|
|
else if (!hasExplicitVisibilityAlready(computation)) {
|
2023-01-14 20:31:01 +00:00
|
|
|
if (std::optional<Visibility> Vis =
|
|
|
|
getExplicitVisibility(Var, computation))
|
2013-02-16 00:17:33 +00:00
|
|
|
LV.mergeVisibility(*Vis, true);
|
|
|
|
}
|
|
|
|
|
2013-04-03 19:27:57 +00:00
|
|
|
if (const VarDecl *Prev = Var->getPreviousDecl()) {
|
|
|
|
LinkageInfo PrevLV = getLVForDecl(Prev, computation);
|
2023-11-02 16:57:29 +00:00
|
|
|
if (PrevLV.getLinkage() != Linkage::Invalid)
|
2013-04-03 19:27:57 +00:00
|
|
|
LV.setLinkage(PrevLV.getLinkage());
|
|
|
|
LV.mergeVisibility(PrevLV);
|
|
|
|
}
|
|
|
|
|
2013-02-16 00:17:33 +00:00
|
|
|
return LV;
|
|
|
|
}
|
2013-06-17 20:04:51 +00:00
|
|
|
|
|
|
|
if (!Var->isStaticLocal())
|
|
|
|
return LinkageInfo::none();
|
2013-02-16 00:17:33 +00:00
|
|
|
}
|
|
|
|
|
2013-06-17 20:04:51 +00:00
|
|
|
ASTContext &Context = D->getASTContext();
|
|
|
|
if (!Context.getLangOpts().CPlusPlus)
|
2013-05-25 17:16:20 +00:00
|
|
|
return LinkageInfo::none();
|
|
|
|
|
2013-07-01 20:22:57 +00:00
|
|
|
const Decl *OuterD = getOutermostFuncOrBlockContext(D);
|
2016-01-12 09:01:25 +00:00
|
|
|
if (!OuterD || OuterD->isInvalidDecl())
|
2013-06-04 13:43:35 +00:00
|
|
|
return LinkageInfo::none();
|
|
|
|
|
2013-07-01 20:22:57 +00:00
|
|
|
LinkageInfo LV;
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *BD = dyn_cast<BlockDecl>(OuterD)) {
|
2013-07-01 20:22:57 +00:00
|
|
|
if (!BD->getBlockManglingNumber())
|
|
|
|
return LinkageInfo::none();
|
|
|
|
|
|
|
|
LV = getLVForClosure(BD->getDeclContext()->getRedeclContext(),
|
|
|
|
BD->getBlockManglingContextDecl(), computation);
|
|
|
|
} else {
|
2015-11-09 17:53:06 +00:00
|
|
|
const auto *FD = cast<FunctionDecl>(OuterD);
|
2013-07-01 20:22:57 +00:00
|
|
|
if (!FD->isInlined() &&
|
2014-12-16 04:52:14 +00:00
|
|
|
!isTemplateInstantiation(FD->getTemplateSpecializationKind()))
|
2013-07-01 20:22:57 +00:00
|
|
|
return LinkageInfo::none();
|
2013-06-04 13:43:35 +00:00
|
|
|
|
2018-08-22 05:43:27 +00:00
|
|
|
// If a function is hidden by -fvisibility-inlines-hidden option and
|
|
|
|
// is not explicitly attributed as a hidden function,
|
|
|
|
// we should not make static local variables in the function hidden.
|
2018-10-10 21:59:56 +00:00
|
|
|
LV = getLVForDecl(FD, computation);
|
2018-08-22 05:43:27 +00:00
|
|
|
if (isa<VarDecl>(D) && useInlineVisibilityHidden(FD) &&
|
2020-09-02 00:17:00 +00:00
|
|
|
!LV.isVisibilityExplicit() &&
|
|
|
|
!Context.getLangOpts().VisibilityInlinesHiddenStaticLocalVar) {
|
2018-08-22 05:43:27 +00:00
|
|
|
assert(cast<VarDecl>(D)->isStaticLocal());
|
2018-10-10 21:59:56 +00:00
|
|
|
// If this was an implicitly hidden inline method, check again for
|
|
|
|
// explicit visibility on the parent class, and use that for static locals
|
|
|
|
// if present.
|
|
|
|
if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
|
|
|
|
LV = getLVForDecl(MD->getParent(), computation);
|
|
|
|
if (!LV.isVisibilityExplicit()) {
|
|
|
|
Visibility globalVisibility =
|
|
|
|
computation.isValueVisibility()
|
|
|
|
? Context.getLangOpts().getValueVisibilityMode()
|
|
|
|
: Context.getLangOpts().getTypeVisibilityMode();
|
2023-11-02 16:57:29 +00:00
|
|
|
return LinkageInfo(Linkage::VisibleNone, globalVisibility,
|
2018-10-10 21:59:56 +00:00
|
|
|
/*visibilityExplicit=*/false);
|
|
|
|
}
|
2018-08-22 05:43:27 +00:00
|
|
|
}
|
2013-07-01 20:22:57 +00:00
|
|
|
}
|
2013-05-27 14:50:21 +00:00
|
|
|
if (!isExternallyVisible(LV.getLinkage()))
|
2013-05-25 17:16:20 +00:00
|
|
|
return LinkageInfo::none();
|
2023-11-02 16:57:29 +00:00
|
|
|
return LinkageInfo(Linkage::VisibleNone, LV.getVisibility(),
|
2013-05-25 17:16:20 +00:00
|
|
|
LV.isVisibilityExplicit());
|
2013-02-16 00:17:33 +00:00
|
|
|
}
|
|
|
|
|
2017-08-09 04:02:49 +00:00
|
|
|
LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
|
2017-09-22 04:25:05 +00:00
|
|
|
LVComputationKind computation,
|
|
|
|
bool IgnoreVarTypeLinkage) {
|
2015-11-10 21:28:44 +00:00
|
|
|
// Internal_linkage attribute overrides other considerations.
|
|
|
|
if (D->hasAttr<InternalLinkageAttr>())
|
2023-07-09 00:26:36 +00:00
|
|
|
return LinkageInfo::internal();
|
2015-11-10 21:28:44 +00:00
|
|
|
|
2010-04-20 23:15:35 +00:00
|
|
|
// Objective-C: treat all Objective-C declarations as having external
|
|
|
|
// linkage.
|
2010-10-29 00:29:13 +00:00
|
|
|
switch (D->getKind()) {
|
2010-04-20 23:15:35 +00:00
|
|
|
default:
|
|
|
|
break;
|
[modules] Simplify and generalize the existing rule for finding hidden
declarations in redeclaration lookup. A declaration is now visible to
lookup if:
* It is visible (not in a module, or in an imported module), or
* We're doing redeclaration lookup and it's externally-visible, or
* We're doing typo correction and looking for unimported decls.
We now support multiple modules having different internal-linkage or no-linkage
definitions of the same name for all entities, not just for functions,
variables, and some typedefs. As previously, if multiple such entities are
visible, any attempt to use them will result in an ambiguity error.
This patch fixes the linkage calculation for a number of entities where we
previously didn't need to get it right (using-declarations, namespace aliases,
and so on). It also classifies enumerators as always having no linkage, which
is a slight deviation from the C++ standard's definition, but not an observable
change outside modules (this change is being discussed on the -core reflector
currently).
This also removes the prior special case for tag lookup, which made some cases
of this work, but also led to bizarre, bogus "must use 'struct' to refer to type
'Foo' in this scope" diagnostics in C++.
llvm-svn: 252960
2015-11-12 22:19:45 +00:00
|
|
|
|
|
|
|
// Per C++ [basic.link]p2, only the names of objects, references,
|
|
|
|
// functions, types, templates, namespaces, and values ever have linkage.
|
|
|
|
//
|
|
|
|
// Note that the name of a typedef, namespace alias, using declaration,
|
|
|
|
// and so on are not the name of the corresponding type, namespace, or
|
|
|
|
// declaration, so they do *not* have linkage.
|
|
|
|
case Decl::ImplicitParam:
|
|
|
|
case Decl::Label:
|
|
|
|
case Decl::NamespaceAlias:
|
2011-12-01 01:28:21 +00:00
|
|
|
case Decl::ParmVar:
|
[modules] Simplify and generalize the existing rule for finding hidden
declarations in redeclaration lookup. A declaration is now visible to
lookup if:
* It is visible (not in a module, or in an imported module), or
* We're doing redeclaration lookup and it's externally-visible, or
* We're doing typo correction and looking for unimported decls.
We now support multiple modules having different internal-linkage or no-linkage
definitions of the same name for all entities, not just for functions,
variables, and some typedefs. As previously, if multiple such entities are
visible, any attempt to use them will result in an ambiguity error.
This patch fixes the linkage calculation for a number of entities where we
previously didn't need to get it right (using-declarations, namespace aliases,
and so on). It also classifies enumerators as always having no linkage, which
is a slight deviation from the C++ standard's definition, but not an observable
change outside modules (this change is being discussed on the -core reflector
currently).
This also removes the prior special case for tag lookup, which made some cases
of this work, but also led to bizarre, bogus "must use 'struct' to refer to type
'Foo' in this scope" diagnostics in C++.
llvm-svn: 252960
2015-11-12 22:19:45 +00:00
|
|
|
case Decl::Using:
|
2021-05-05 15:55:02 +00:00
|
|
|
case Decl::UsingEnum:
|
[modules] Simplify and generalize the existing rule for finding hidden
declarations in redeclaration lookup. A declaration is now visible to
lookup if:
* It is visible (not in a module, or in an imported module), or
* We're doing redeclaration lookup and it's externally-visible, or
* We're doing typo correction and looking for unimported decls.
We now support multiple modules having different internal-linkage or no-linkage
definitions of the same name for all entities, not just for functions,
variables, and some typedefs. As previously, if multiple such entities are
visible, any attempt to use them will result in an ambiguity error.
This patch fixes the linkage calculation for a number of entities where we
previously didn't need to get it right (using-declarations, namespace aliases,
and so on). It also classifies enumerators as always having no linkage, which
is a slight deviation from the C++ standard's definition, but not an observable
change outside modules (this change is being discussed on the -core reflector
currently).
This also removes the prior special case for tag lookup, which made some cases
of this work, but also led to bizarre, bogus "must use 'struct' to refer to type
'Foo' in this scope" diagnostics in C++.
llvm-svn: 252960
2015-11-12 22:19:45 +00:00
|
|
|
case Decl::UsingShadow:
|
|
|
|
case Decl::UsingDirective:
|
2011-12-01 01:28:21 +00:00
|
|
|
return LinkageInfo::none();
|
[modules] Simplify and generalize the existing rule for finding hidden
declarations in redeclaration lookup. A declaration is now visible to
lookup if:
* It is visible (not in a module, or in an imported module), or
* We're doing redeclaration lookup and it's externally-visible, or
* We're doing typo correction and looking for unimported decls.
We now support multiple modules having different internal-linkage or no-linkage
definitions of the same name for all entities, not just for functions,
variables, and some typedefs. As previously, if multiple such entities are
visible, any attempt to use them will result in an ambiguity error.
This patch fixes the linkage calculation for a number of entities where we
previously didn't need to get it right (using-declarations, namespace aliases,
and so on). It also classifies enumerators as always having no linkage, which
is a slight deviation from the C++ standard's definition, but not an observable
change outside modules (this change is being discussed on the -core reflector
currently).
This also removes the prior special case for tag lookup, which made some cases
of this work, but also led to bizarre, bogus "must use 'struct' to refer to type
'Foo' in this scope" diagnostics in C++.
llvm-svn: 252960
2015-11-12 22:19:45 +00:00
|
|
|
|
2015-11-13 03:52:13 +00:00
|
|
|
case Decl::EnumConstant:
|
|
|
|
// C++ [basic.link]p4: an enumerator has the linkage of its enumeration.
|
2017-07-01 00:06:27 +00:00
|
|
|
if (D->getASTContext().getLangOpts().CPlusPlus)
|
|
|
|
return getLVForDecl(cast<EnumDecl>(D->getDeclContext()), computation);
|
|
|
|
return LinkageInfo::visible_none();
|
2015-11-13 03:52:13 +00:00
|
|
|
|
[modules] Simplify and generalize the existing rule for finding hidden
declarations in redeclaration lookup. A declaration is now visible to
lookup if:
* It is visible (not in a module, or in an imported module), or
* We're doing redeclaration lookup and it's externally-visible, or
* We're doing typo correction and looking for unimported decls.
We now support multiple modules having different internal-linkage or no-linkage
definitions of the same name for all entities, not just for functions,
variables, and some typedefs. As previously, if multiple such entities are
visible, any attempt to use them will result in an ambiguity error.
This patch fixes the linkage calculation for a number of entities where we
previously didn't need to get it right (using-declarations, namespace aliases,
and so on). It also classifies enumerators as always having no linkage, which
is a slight deviation from the C++ standard's definition, but not an observable
change outside modules (this change is being discussed on the -core reflector
currently).
This also removes the prior special case for tag lookup, which made some cases
of this work, but also led to bizarre, bogus "must use 'struct' to refer to type
'Foo' in this scope" diagnostics in C++.
llvm-svn: 252960
2015-11-12 22:19:45 +00:00
|
|
|
case Decl::Typedef:
|
|
|
|
case Decl::TypeAlias:
|
|
|
|
// A typedef declaration has linkage if it gives a type a name for
|
|
|
|
// linkage purposes.
|
2017-07-01 20:44:49 +00:00
|
|
|
if (!cast<TypedefNameDecl>(D)
|
[modules] Simplify and generalize the existing rule for finding hidden
declarations in redeclaration lookup. A declaration is now visible to
lookup if:
* It is visible (not in a module, or in an imported module), or
* We're doing redeclaration lookup and it's externally-visible, or
* We're doing typo correction and looking for unimported decls.
We now support multiple modules having different internal-linkage or no-linkage
definitions of the same name for all entities, not just for functions,
variables, and some typedefs. As previously, if multiple such entities are
visible, any attempt to use them will result in an ambiguity error.
This patch fixes the linkage calculation for a number of entities where we
previously didn't need to get it right (using-declarations, namespace aliases,
and so on). It also classifies enumerators as always having no linkage, which
is a slight deviation from the C++ standard's definition, but not an observable
change outside modules (this change is being discussed on the -core reflector
currently).
This also removes the prior special case for tag lookup, which made some cases
of this work, but also led to bizarre, bogus "must use 'struct' to refer to type
'Foo' in this scope" diagnostics in C++.
llvm-svn: 252960
2015-11-12 22:19:45 +00:00
|
|
|
->getAnonDeclWithTypedefName(/*AnyRedecl*/true))
|
|
|
|
return LinkageInfo::none();
|
|
|
|
break;
|
|
|
|
|
2010-10-22 21:05:15 +00:00
|
|
|
case Decl::TemplateTemplateParm: // count these as external
|
|
|
|
case Decl::NonTypeTemplateParm:
|
2010-04-20 23:15:35 +00:00
|
|
|
case Decl::ObjCAtDefsField:
|
|
|
|
case Decl::ObjCCategory:
|
|
|
|
case Decl::ObjCCategoryImpl:
|
|
|
|
case Decl::ObjCCompatibleAlias:
|
|
|
|
case Decl::ObjCImplementation:
|
|
|
|
case Decl::ObjCMethod:
|
|
|
|
case Decl::ObjCProperty:
|
|
|
|
case Decl::ObjCPropertyImpl:
|
|
|
|
case Decl::ObjCProtocol:
|
2017-07-07 20:04:28 +00:00
|
|
|
return getExternalLinkageFor(D);
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2012-02-21 04:17:39 +00:00
|
|
|
case Decl::CXXRecord: {
|
2015-11-09 17:53:06 +00:00
|
|
|
const auto *Record = cast<CXXRecordDecl>(D);
|
2012-02-21 04:17:39 +00:00
|
|
|
if (Record->isLambda()) {
|
[hip][cuda] Fix the extended lambda name mangling issue.
Summary:
- HIP/CUDA host side needs to use device kernel symbol name to match the
device side binaries. Without a consistent naming between host- and
device-side compilations, it's risky that wrong device binaries are
executed. Consistent naming is usually not an issue until unnamed
types are used, especially the lambda. In this patch, the consistent
name mangling is addressed for the extended lambdas, i.e. the lambdas
annotated with `__device__`.
- In [Itanium C++ ABI][1], the mangling of the lambda is generally
unspecified unless, in certain cases, ODR rule is required to ensure
consisent naming cross TUs. The extended lambda is such a case as its
name may be part of a device kernel function, e.g., the extended
lambda is used as a template argument and etc. Thus, we need to force
ODR for extended lambdas as they are referenced in both device- and
host-side TUs. Furthermore, if a extended lambda is nested in other
(extended or not) lambdas, those lambdas are required to follow ODR
naming as well. This patch revises the current lambda mangle numbering
to force ODR from an extended lambda to all its parent lambdas.
- On the other side, the aforementioned ODR naming should not change
those lambdas' original linkages, i.e., we cannot replace the original
`internal` with `linkonce_odr`; otherwise, we may violate ODR in
general. This patch introduces a new field `HasKnownInternalLinkage`
in lambda data to decouple the current linkage calculation based on
mangling number assigned.
[1]: https://itanium-cxx-abi.github.io/cxx-abi/abi.html
Reviewers: tra, rsmith, yaxunl, martong, shafik
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D68818
llvm-svn: 375309
2019-10-19 00:15:19 +00:00
|
|
|
if (Record->hasKnownLambdaInternalLinkage() ||
|
|
|
|
!Record->getLambdaManglingNumber()) {
|
2012-02-21 04:17:39 +00:00
|
|
|
// This lambda has no mangling number, so it's internal.
|
2023-07-09 00:26:36 +00:00
|
|
|
return LinkageInfo::internal();
|
2012-02-21 04:17:39 +00:00
|
|
|
}
|
|
|
|
|
2013-10-01 02:51:53 +00:00
|
|
|
return getLVForClosure(
|
2020-02-07 17:58:17 +00:00
|
|
|
Record->getDeclContext()->getRedeclContext(),
|
|
|
|
Record->getLambdaContextDecl(), computation);
|
2012-02-21 04:17:39 +00:00
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2012-02-21 04:17:39 +00:00
|
|
|
break;
|
|
|
|
}
|
2020-09-21 06:18:04 +00:00
|
|
|
|
|
|
|
case Decl::TemplateParamObject: {
|
|
|
|
// The template parameter object can be referenced from anywhere its type
|
|
|
|
// and value can be referenced.
|
|
|
|
auto *TPO = cast<TemplateParamObjectDecl>(D);
|
|
|
|
LinkageInfo LV = getLVForType(*TPO->getType(), computation);
|
|
|
|
LV.merge(getLVForValue(TPO->getValue(), computation));
|
|
|
|
return LV;
|
|
|
|
}
|
2010-04-20 23:15:35 +00:00
|
|
|
}
|
|
|
|
|
2009-11-25 22:24:25 +00:00
|
|
|
// Handle linkage for namespace-scope names.
|
2010-10-29 00:29:13 +00:00
|
|
|
if (D->getDeclContext()->getRedeclContext()->isFileContext())
|
2017-09-22 04:25:05 +00:00
|
|
|
return getLVForNamespaceScopeDecl(D, computation, IgnoreVarTypeLinkage);
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2009-11-25 22:24:25 +00:00
|
|
|
// 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.
|
2010-10-29 00:29:13 +00:00
|
|
|
if (D->getDeclContext()->isRecord())
|
2017-09-22 04:25:05 +00:00
|
|
|
return getLVForClassMember(D, computation, IgnoreVarTypeLinkage);
|
2009-11-25 22:24:25 +00:00
|
|
|
|
|
|
|
// 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.
|
2013-02-16 00:17:33 +00:00
|
|
|
if (D->getDeclContext()->isFunctionOrMethod())
|
|
|
|
return getLVForLocalDecl(D, computation);
|
2009-11-25 22:24:25 +00:00
|
|
|
|
|
|
|
// C++ [basic.link]p6:
|
|
|
|
// Names not covered by these rules have no linkage.
|
2010-10-30 11:50:40 +00:00
|
|
|
return LinkageInfo::none();
|
2010-10-22 21:05:15 +00:00
|
|
|
}
|
2009-11-25 22:24:25 +00:00
|
|
|
|
2017-08-09 04:02:49 +00:00
|
|
|
/// getLVForDecl - Get the linkage and visibility for the given declaration.
|
|
|
|
LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D,
|
|
|
|
LVComputationKind computation) {
|
|
|
|
// Internal_linkage attribute overrides other considerations.
|
|
|
|
if (D->hasAttr<InternalLinkageAttr>())
|
2023-07-09 00:26:36 +00:00
|
|
|
return LinkageInfo::internal();
|
2015-11-10 21:28:44 +00:00
|
|
|
|
2017-09-22 02:22:32 +00:00
|
|
|
if (computation.IgnoreAllVisibility && D->hasCachedLinkage())
|
2017-08-09 04:02:49 +00:00
|
|
|
return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false);
|
2013-05-28 19:43:11 +00:00
|
|
|
|
2023-01-14 20:31:01 +00:00
|
|
|
if (std::optional<LinkageInfo> LI = lookup(D, computation))
|
2017-08-09 04:12:17 +00:00
|
|
|
return *LI;
|
|
|
|
|
2017-08-09 04:02:49 +00:00
|
|
|
LinkageInfo LV = computeLVForDecl(D, computation);
|
|
|
|
if (D->hasCachedLinkage())
|
|
|
|
assert(D->getCachedLinkage() == LV.getLinkage());
|
2013-05-28 19:43:11 +00:00
|
|
|
|
2017-08-09 04:02:49 +00:00
|
|
|
D->setCachedLinkage(LV.getLinkage());
|
2017-08-09 04:12:17 +00:00
|
|
|
cache(D, computation, LV);
|
2013-05-28 19:43:11 +00:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
2017-08-09 04:02:49 +00:00
|
|
|
// In C (because of gnu inline) and in c++ with microsoft extensions an
|
|
|
|
// static can follow an extern, so we can have two decls with different
|
|
|
|
// linkages.
|
|
|
|
const LangOptions &Opts = D->getASTContext().getLangOpts();
|
|
|
|
if (!Opts.CPlusPlus || Opts.MicrosoftExt)
|
|
|
|
return LV;
|
2013-05-28 19:43:11 +00:00
|
|
|
|
2017-08-09 04:02:49 +00:00
|
|
|
// We have just computed the linkage for this decl. By induction we know
|
|
|
|
// that all other computed linkages match, check that the one we just
|
|
|
|
// computed also does.
|
|
|
|
NamedDecl *Old = nullptr;
|
2022-09-04 06:27:27 +00:00
|
|
|
for (auto *I : D->redecls()) {
|
2017-08-09 04:02:49 +00:00
|
|
|
auto *T = cast<NamedDecl>(I);
|
|
|
|
if (T == D)
|
|
|
|
continue;
|
|
|
|
if (!T->isInvalidDecl() && T->hasCachedLinkage()) {
|
|
|
|
Old = T;
|
|
|
|
break;
|
2013-05-28 19:43:11 +00:00
|
|
|
}
|
2017-08-09 04:02:49 +00:00
|
|
|
}
|
|
|
|
assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage());
|
2013-05-28 19:43:11 +00:00
|
|
|
#endif
|
|
|
|
|
2017-08-09 04:02:49 +00:00
|
|
|
return LV;
|
2015-06-22 23:07:51 +00:00
|
|
|
}
|
2013-05-28 19:43:11 +00:00
|
|
|
|
2017-08-09 04:02:49 +00:00
|
|
|
LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) {
|
2021-03-09 15:38:00 +00:00
|
|
|
NamedDecl::ExplicitVisibilityKind EK = usesTypeVisibility(D)
|
|
|
|
? NamedDecl::VisibilityForType
|
|
|
|
: NamedDecl::VisibilityForValue;
|
|
|
|
LVComputationKind CK(EK);
|
|
|
|
return getLVForDecl(D, D->getASTContext().getLangOpts().IgnoreXCOFFVisibility
|
|
|
|
? CK.forLinkageOnly()
|
|
|
|
: CK);
|
2013-05-28 19:43:11 +00:00
|
|
|
}
|
|
|
|
|
2017-10-10 22:33:17 +00:00
|
|
|
Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const {
|
2022-01-18 15:14:08 +00:00
|
|
|
if (isa<NamespaceDecl>(this))
|
|
|
|
// Namespaces never have module linkage. It is the entities within them
|
|
|
|
// that [may] do.
|
|
|
|
return nullptr;
|
|
|
|
|
2017-09-04 05:37:53 +00:00
|
|
|
Module *M = getOwningModule();
|
|
|
|
if (!M)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
switch (M->Kind) {
|
|
|
|
case Module::ModuleMapModule:
|
|
|
|
// Module map modules have no special linkage semantics.
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
case Module::ModuleInterfaceUnit:
|
2022-06-03 09:43:38 +00:00
|
|
|
case Module::ModuleImplementationUnit:
|
2021-11-29 08:05:56 +00:00
|
|
|
case Module::ModulePartitionInterface:
|
|
|
|
case Module::ModulePartitionImplementation:
|
2017-09-04 05:37:53 +00:00
|
|
|
return M;
|
|
|
|
|
2020-09-20 08:29:14 +00:00
|
|
|
case Module::ModuleHeaderUnit:
|
2023-03-03 02:31:48 +00:00
|
|
|
case Module::ExplicitGlobalModuleFragment:
|
|
|
|
case Module::ImplicitGlobalModuleFragment: {
|
2017-09-04 05:37:53 +00:00
|
|
|
// External linkage declarations in the global module have no owning module
|
|
|
|
// for linkage purposes. But internal linkage declarations in the global
|
|
|
|
// module fragment of a particular module are owned by that module for
|
|
|
|
// linkage purposes.
|
2022-02-01 15:49:28 +00:00
|
|
|
// FIXME: p1815 removes the need for this distinction -- there are no
|
|
|
|
// internal linkage declarations that need to be referred to from outside
|
|
|
|
// this TU.
|
2017-10-10 22:33:17 +00:00
|
|
|
if (IgnoreLinkage)
|
|
|
|
return nullptr;
|
|
|
|
bool InternalLinkage;
|
|
|
|
if (auto *ND = dyn_cast<NamedDecl>(this))
|
|
|
|
InternalLinkage = !ND->hasExternalFormalLinkage();
|
2022-02-01 15:49:28 +00:00
|
|
|
else
|
|
|
|
InternalLinkage = isInAnonymousNamespace();
|
2020-09-20 08:29:14 +00:00
|
|
|
return InternalLinkage ? M->Kind == Module::ModuleHeaderUnit ? M : M->Parent
|
|
|
|
: nullptr;
|
2017-09-04 05:37:53 +00:00
|
|
|
}
|
2019-04-18 21:12:54 +00:00
|
|
|
|
|
|
|
case Module::PrivateModuleFragment:
|
|
|
|
// The private module fragment is part of its containing module for linkage
|
|
|
|
// purposes.
|
|
|
|
return M->Parent;
|
2017-11-13 23:01:27 +00:00
|
|
|
}
|
2017-09-04 05:37:53 +00:00
|
|
|
|
|
|
|
llvm_unreachable("unknown module kind");
|
|
|
|
}
|
|
|
|
|
2023-05-02 15:53:48 +00:00
|
|
|
void NamedDecl::printName(raw_ostream &OS, const PrintingPolicy &Policy) const {
|
|
|
|
Name.print(OS, Policy);
|
2022-10-14 12:17:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void NamedDecl::printName(raw_ostream &OS) const {
|
|
|
|
printName(OS, getASTContext().getPrintingPolicy());
|
2016-08-11 22:25:46 +00:00
|
|
|
}
|
|
|
|
|
2009-02-04 17:27:36 +00:00
|
|
|
std::string NamedDecl::getQualifiedNameAsString() const {
|
2013-02-23 13:53:57 +00:00
|
|
|
std::string QualName;
|
|
|
|
llvm::raw_string_ostream OS(QualName);
|
2014-01-03 18:42:48 +00:00
|
|
|
printQualifiedName(OS, getASTContext().getPrintingPolicy());
|
2021-12-09 22:52:30 +00:00
|
|
|
return QualName;
|
2013-02-23 13:53:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void NamedDecl::printQualifiedName(raw_ostream &OS) const {
|
|
|
|
printQualifiedName(OS, getASTContext().getPrintingPolicy());
|
|
|
|
}
|
|
|
|
|
|
|
|
void NamedDecl::printQualifiedName(raw_ostream &OS,
|
|
|
|
const PrintingPolicy &P) const {
|
2019-09-25 15:46:04 +00:00
|
|
|
if (getDeclContext()->isFunctionOrMethod()) {
|
|
|
|
// We do not print '(anonymous)' for function parameters without name.
|
2022-10-14 12:17:16 +00:00
|
|
|
printName(OS, P);
|
2019-09-25 15:46:04 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
printNestedNameSpecifier(OS, P);
|
2020-04-15 06:35:35 +00:00
|
|
|
if (getDeclName())
|
2019-09-25 15:46:04 +00:00
|
|
|
OS << *this;
|
2020-04-15 06:35:35 +00:00
|
|
|
else {
|
|
|
|
// Give the printName override a chance to pick a different name before we
|
|
|
|
// fall back to "(anonymous)".
|
|
|
|
SmallString<64> NameBuffer;
|
|
|
|
llvm::raw_svector_ostream NameOS(NameBuffer);
|
2022-10-14 12:17:16 +00:00
|
|
|
printName(NameOS, P);
|
2020-04-15 06:35:35 +00:00
|
|
|
if (NameBuffer.empty())
|
|
|
|
OS << "(anonymous)";
|
|
|
|
else
|
|
|
|
OS << NameBuffer;
|
|
|
|
}
|
2019-09-25 15:46:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void NamedDecl::printNestedNameSpecifier(raw_ostream &OS) const {
|
|
|
|
printNestedNameSpecifier(OS, getASTContext().getPrintingPolicy());
|
|
|
|
}
|
|
|
|
|
|
|
|
void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
|
|
|
|
const PrintingPolicy &P) const {
|
2009-02-04 17:27:36 +00:00
|
|
|
const DeclContext *Ctx = getDeclContext();
|
|
|
|
|
2019-04-04 20:13:22 +00:00
|
|
|
// For ObjC methods and properties, look through categories and use the
|
|
|
|
// interface as context.
|
2020-05-19 13:10:10 +00:00
|
|
|
if (auto *MD = dyn_cast<ObjCMethodDecl>(this)) {
|
2017-03-07 09:26:07 +00:00
|
|
|
if (auto *ID = MD->getClassInterface())
|
|
|
|
Ctx = ID;
|
2020-05-19 13:10:10 +00:00
|
|
|
} else if (auto *PD = dyn_cast<ObjCPropertyDecl>(this)) {
|
2019-04-04 20:13:22 +00:00
|
|
|
if (auto *MD = PD->getGetterMethodDecl())
|
|
|
|
if (auto *ID = MD->getClassInterface())
|
|
|
|
Ctx = ID;
|
2020-05-19 13:10:10 +00:00
|
|
|
} else if (auto *ID = dyn_cast<ObjCIvarDecl>(this)) {
|
|
|
|
if (auto *CI = ID->getContainingInterface())
|
|
|
|
Ctx = CI;
|
2019-04-04 20:13:22 +00:00
|
|
|
}
|
2017-03-07 09:26:07 +00:00
|
|
|
|
2019-09-25 15:46:04 +00:00
|
|
|
if (Ctx->isFunctionOrMethod())
|
2013-02-23 13:53:57 +00:00
|
|
|
return;
|
2009-02-04 17:27:36 +00:00
|
|
|
|
2017-11-13 23:01:27 +00:00
|
|
|
using ContextsTy = SmallVector<const DeclContext *, 8>;
|
2010-04-28 14:33:51 +00:00
|
|
|
ContextsTy Contexts;
|
|
|
|
|
2018-02-02 13:34:47 +00:00
|
|
|
// Collect named contexts.
|
2020-11-11 22:34:20 +00:00
|
|
|
DeclarationName NameInScope = getDeclName();
|
|
|
|
for (; Ctx; Ctx = Ctx->getParent()) {
|
|
|
|
// Suppress anonymous namespace if requested.
|
|
|
|
if (P.SuppressUnwrittenScope && isa<NamespaceDecl>(Ctx) &&
|
|
|
|
cast<NamespaceDecl>(Ctx)->isAnonymousNamespace())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Suppress inline namespace if it doesn't make the result ambiguous.
|
|
|
|
if (P.SuppressInlineNamespace && Ctx->isInlineNamespace() && NameInScope &&
|
2021-03-17 08:56:05 +00:00
|
|
|
cast<NamespaceDecl>(Ctx)->isRedundantInlineQualifierFor(NameInScope))
|
2020-11-11 22:34:20 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Skip non-named contexts such as linkage specifications and ExportDecls.
|
|
|
|
const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx);
|
|
|
|
if (!ND)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Contexts.push_back(Ctx);
|
|
|
|
NameInScope = ND->getDeclName();
|
2013-02-23 13:53:57 +00:00
|
|
|
}
|
2010-04-28 14:33:51 +00:00
|
|
|
|
2021-11-07 13:24:33 +00:00
|
|
|
for (const DeclContext *DC : llvm::reverse(Contexts)) {
|
2016-06-23 00:15:04 +00:00
|
|
|
if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
|
2013-02-22 15:46:01 +00:00
|
|
|
OS << Spec->getName();
|
2009-05-18 17:01:57 +00:00
|
|
|
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
|
2020-11-13 04:55:21 +00:00
|
|
|
printTemplateArgumentList(
|
|
|
|
OS, TemplateArgs.asArray(), P,
|
|
|
|
Spec->getSpecializedTemplate()->getTemplateParameters());
|
2016-06-23 00:15:04 +00:00
|
|
|
} else if (const auto *ND = dyn_cast<NamespaceDecl>(DC)) {
|
2015-12-16 02:04:40 +00:00
|
|
|
if (ND->isAnonymousNamespace()) {
|
|
|
|
OS << (P.MSVCFormatting ? "`anonymous namespace\'"
|
|
|
|
: "(anonymous namespace)");
|
|
|
|
}
|
2009-12-24 23:15:03 +00:00
|
|
|
else
|
2011-10-14 18:45:37 +00:00
|
|
|
OS << *ND;
|
2016-06-23 00:15:04 +00:00
|
|
|
} else if (const auto *RD = dyn_cast<RecordDecl>(DC)) {
|
2010-04-28 14:33:51 +00:00
|
|
|
if (!RD->getIdentifier())
|
2014-04-02 05:58:29 +00:00
|
|
|
OS << "(anonymous " << RD->getKindName() << ')';
|
2010-04-28 14:33:51 +00:00
|
|
|
else
|
2011-10-14 18:45:37 +00:00
|
|
|
OS << *RD;
|
2016-06-23 00:15:04 +00:00
|
|
|
} else if (const auto *FD = dyn_cast<FunctionDecl>(DC)) {
|
2014-05-12 05:36:57 +00:00
|
|
|
const FunctionProtoType *FT = nullptr;
|
2009-12-28 03:19:38 +00:00
|
|
|
if (FD->hasWrittenPrototype())
|
2012-08-30 22:22:09 +00:00
|
|
|
FT = dyn_cast<FunctionProtoType>(FD->getType()->castAs<FunctionType>());
|
2009-12-28 03:19:38 +00:00
|
|
|
|
2011-10-14 18:45:37 +00:00
|
|
|
OS << *FD << '(';
|
2009-12-28 03:19:38 +00:00
|
|
|
if (FT) {
|
|
|
|
unsigned NumParams = FD->getNumParams();
|
|
|
|
for (unsigned i = 0; i < NumParams; ++i) {
|
|
|
|
if (i)
|
2010-04-28 14:33:51 +00:00
|
|
|
OS << ", ";
|
2012-05-05 04:20:37 +00:00
|
|
|
OS << FD->getParamDecl(i)->getType().stream(P);
|
2009-12-28 03:19:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (FT->isVariadic()) {
|
|
|
|
if (NumParams > 0)
|
2010-04-28 14:33:51 +00:00
|
|
|
OS << ", ";
|
|
|
|
OS << "...";
|
2009-12-28 03:19:38 +00:00
|
|
|
}
|
|
|
|
}
|
2010-04-28 14:33:51 +00:00
|
|
|
OS << ')';
|
2016-06-23 00:15:04 +00:00
|
|
|
} else if (const auto *ED = dyn_cast<EnumDecl>(DC)) {
|
2015-11-09 16:45:17 +00:00
|
|
|
// C++ [dcl.enum]p10: Each enum-name and each unscoped
|
|
|
|
// enumerator is declared in the scope that immediately contains
|
|
|
|
// the enum-specifier. Each scoped enumerator is declared in the
|
|
|
|
// scope of the enumeration.
|
2017-12-21 21:47:22 +00:00
|
|
|
// For the case of unscoped enumerator, do not include in the qualified
|
2017-12-26 18:01:19 +00:00
|
|
|
// name any information about its enum enclosing scope, as its visibility
|
2017-12-21 21:47:22 +00:00
|
|
|
// is global.
|
|
|
|
if (ED->isScoped())
|
2015-11-09 16:45:17 +00:00
|
|
|
OS << *ED;
|
|
|
|
else
|
|
|
|
continue;
|
2010-04-28 14:33:51 +00:00
|
|
|
} else {
|
2016-06-23 00:15:04 +00:00
|
|
|
OS << *cast<NamedDecl>(DC);
|
2010-04-28 14:33:51 +00:00
|
|
|
}
|
|
|
|
OS << "::";
|
2009-02-04 17:27:36 +00:00
|
|
|
}
|
2013-02-23 13:53:57 +00:00
|
|
|
}
|
2009-02-04 17:27:36 +00:00
|
|
|
|
2013-02-23 13:53:57 +00:00
|
|
|
void NamedDecl::getNameForDiagnostic(raw_ostream &OS,
|
|
|
|
const PrintingPolicy &Policy,
|
|
|
|
bool Qualified) const {
|
|
|
|
if (Qualified)
|
|
|
|
printQualifiedName(OS, Policy);
|
|
|
|
else
|
2022-10-14 12:17:16 +00:00
|
|
|
printName(OS, Policy);
|
2009-02-04 17:27:36 +00:00
|
|
|
}
|
|
|
|
|
2015-02-10 03:28:10 +00:00
|
|
|
template<typename T> static bool isRedeclarableImpl(Redeclarable<T> *) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
static bool isRedeclarableImpl(...) { return false; }
|
|
|
|
static bool isRedeclarable(Decl::Kind K) {
|
|
|
|
switch (K) {
|
|
|
|
#define DECL(Type, Base) \
|
|
|
|
case Decl::Type: \
|
|
|
|
return isRedeclarableImpl((Type##Decl *)nullptr);
|
|
|
|
#define ABSTRACT_DECL(DECL)
|
|
|
|
#include "clang/AST/DeclNodes.inc"
|
2009-02-03 19:21:40 +00:00
|
|
|
}
|
2015-02-10 03:28:10 +00:00
|
|
|
llvm_unreachable("unknown decl kind");
|
|
|
|
}
|
2009-09-09 15:08:12 +00:00
|
|
|
|
2015-02-10 03:28:10 +00:00
|
|
|
bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
|
|
|
|
assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
|
2008-12-23 21:05:05 +00:00
|
|
|
|
2015-03-05 23:24:12 +00:00
|
|
|
// Never replace one imported declaration with another; we need both results
|
|
|
|
// when re-exporting.
|
|
|
|
if (OldD->isFromASTFile() && isFromASTFile())
|
|
|
|
return false;
|
|
|
|
|
2015-11-03 03:13:11 +00:00
|
|
|
// A kind mismatch implies that the declaration is not replaced.
|
|
|
|
if (OldD->getKind() != getKind())
|
2009-02-22 19:35:57 +00:00
|
|
|
return false;
|
2009-09-09 15:08:12 +00:00
|
|
|
|
2015-11-03 03:13:11 +00:00
|
|
|
// For method declarations, we never replace. (Why?)
|
|
|
|
if (isa<ObjCMethodDecl>(this))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// For parameters, pick the newer one. This is either an error or (in
|
|
|
|
// Objective-C) permitted as an extension.
|
|
|
|
if (isa<ParmVarDecl>(this))
|
|
|
|
return true;
|
|
|
|
|
2015-02-10 03:28:10 +00:00
|
|
|
// Inline namespaces can give us two declarations with the same
|
|
|
|
// name and kind in the same scope but different contexts; we should
|
|
|
|
// keep both declarations in this case.
|
|
|
|
if (!this->getDeclContext()->getRedeclContext()->Equals(
|
|
|
|
OldD->getDeclContext()->getRedeclContext()))
|
|
|
|
return false;
|
2009-10-09 21:13:30 +00:00
|
|
|
|
2015-11-03 03:13:11 +00:00
|
|
|
// Using declarations can be replaced if they import the same name from the
|
|
|
|
// same context.
|
2015-02-10 03:28:10 +00:00
|
|
|
if (auto *UD = dyn_cast<UsingDecl>(this)) {
|
2011-02-25 00:36:19 +00:00
|
|
|
ASTContext &Context = getASTContext();
|
2015-02-10 03:28:10 +00:00
|
|
|
return Context.getCanonicalNestedNameSpecifier(UD->getQualifier()) ==
|
2011-02-25 00:36:19 +00:00
|
|
|
Context.getCanonicalNestedNameSpecifier(
|
2015-02-10 03:28:10 +00:00
|
|
|
cast<UsingDecl>(OldD)->getQualifier());
|
2013-08-20 00:39:40 +00:00
|
|
|
}
|
2015-02-10 03:28:10 +00:00
|
|
|
if (auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(this)) {
|
2013-08-20 00:39:40 +00:00
|
|
|
ASTContext &Context = getASTContext();
|
2015-02-10 03:28:10 +00:00
|
|
|
return Context.getCanonicalNestedNameSpecifier(UUVD->getQualifier()) ==
|
2013-08-20 00:39:40 +00:00
|
|
|
Context.getCanonicalNestedNameSpecifier(
|
|
|
|
cast<UnresolvedUsingValueDecl>(OldD)->getQualifier());
|
2011-02-25 00:36:19 +00:00
|
|
|
}
|
2010-11-04 08:48:52 +00:00
|
|
|
|
2015-11-03 03:13:11 +00:00
|
|
|
if (isRedeclarable(getKind())) {
|
|
|
|
if (getCanonicalDecl() != OldD->getCanonicalDecl())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (IsKnownNewer)
|
|
|
|
return true;
|
|
|
|
|
2015-02-10 03:28:10 +00:00
|
|
|
// Check whether this is actually newer than OldD. We want to keep the
|
|
|
|
// newer declaration. This loop will usually only iterate once, because
|
|
|
|
// OldD is usually the previous declaration.
|
2022-09-04 06:27:27 +00:00
|
|
|
for (auto *D : redecls()) {
|
2015-02-10 03:28:10 +00:00
|
|
|
if (D == OldD)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// If we reach the canonical declaration, then OldD is not actually older
|
|
|
|
// than this one.
|
|
|
|
//
|
|
|
|
// FIXME: In this case, we should not add this decl to the lookup table.
|
|
|
|
if (D->isCanonicalDecl())
|
|
|
|
return false;
|
|
|
|
}
|
2015-11-03 03:13:11 +00:00
|
|
|
|
|
|
|
// It's a newer declaration of the same kind of declaration in the same
|
|
|
|
// scope: we want this decl instead of the existing one.
|
|
|
|
return true;
|
2015-02-10 03:28:10 +00:00
|
|
|
}
|
2014-03-17 21:46:03 +00:00
|
|
|
|
2015-11-03 03:13:11 +00:00
|
|
|
// In all other cases, we need to keep both declarations in case they have
|
|
|
|
// different visibility. Any attempt to use the name will result in an
|
|
|
|
// ambiguity if more than one is visible.
|
|
|
|
return false;
|
2008-12-23 21:05:05 +00:00
|
|
|
}
|
|
|
|
|
2009-02-24 20:03:32 +00:00
|
|
|
bool NamedDecl::hasLinkage() const {
|
2023-11-02 16:57:29 +00:00
|
|
|
switch (getFormalLinkage()) {
|
|
|
|
case Linkage::Invalid:
|
|
|
|
llvm_unreachable("Linkage hasn't been computed!");
|
|
|
|
case Linkage::None:
|
|
|
|
return false;
|
|
|
|
case Linkage::Internal:
|
|
|
|
return true;
|
|
|
|
case Linkage::UniqueExternal:
|
|
|
|
case Linkage::VisibleNone:
|
|
|
|
llvm_unreachable("Non-formal linkage is not allowed here!");
|
|
|
|
case Linkage::Module:
|
|
|
|
case Linkage::External:
|
|
|
|
return true;
|
|
|
|
}
|
2023-11-03 09:49:31 +00:00
|
|
|
llvm_unreachable("Unhandled Linkage enum");
|
2009-02-24 20:03:32 +00:00
|
|
|
}
|
2009-01-20 01:17:11 +00:00
|
|
|
|
2012-03-08 18:20:41 +00:00
|
|
|
NamedDecl *NamedDecl::getUnderlyingDeclImpl() {
|
2009-06-26 06:29:23 +00:00
|
|
|
NamedDecl *ND = this;
|
2022-05-16 11:38:13 +00:00
|
|
|
if (auto *UD = dyn_cast<UsingShadowDecl>(ND))
|
2012-03-08 21:00:45 +00:00
|
|
|
ND = UD->getTargetDecl();
|
|
|
|
|
2015-11-09 17:53:06 +00:00
|
|
|
if (auto *AD = dyn_cast<ObjCCompatibleAliasDecl>(ND))
|
2012-03-08 21:00:45 +00:00
|
|
|
return AD->getClassInterface();
|
|
|
|
|
2015-12-29 23:34:32 +00:00
|
|
|
if (auto *AD = dyn_cast<NamespaceAliasDecl>(ND))
|
|
|
|
return AD->getNamespace();
|
|
|
|
|
2012-03-08 21:00:45 +00:00
|
|
|
return ND;
|
2009-06-26 06:29:23 +00:00
|
|
|
}
|
|
|
|
|
2010-04-06 21:38:20 +00:00
|
|
|
bool NamedDecl::isCXXInstanceMember() const {
|
2012-03-08 02:08:05 +00:00
|
|
|
if (!isCXXClassMember())
|
|
|
|
return false;
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2010-04-06 21:38:20 +00:00
|
|
|
const NamedDecl *D = this;
|
|
|
|
if (isa<UsingShadowDecl>(D))
|
|
|
|
D = cast<UsingShadowDecl>(D)->getTargetDecl();
|
|
|
|
|
2013-04-16 07:28:30 +00:00
|
|
|
if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<MSPropertyDecl>(D))
|
2010-04-06 21:38:20 +00:00
|
|
|
return true;
|
2023-09-13 12:53:27 +00:00
|
|
|
if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(D->getAsFunction()))
|
2014-01-22 07:29:52 +00:00
|
|
|
return MD->isInstance();
|
2010-04-06 21:38:20 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-08-21 00:31:54 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DeclaratorDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-07-06 18:42:40 +00:00
|
|
|
template <typename DeclT>
|
|
|
|
static SourceLocation getTemplateOrInnerLocStart(const DeclT *decl) {
|
|
|
|
if (decl->getNumTemplateParameterLists() > 0)
|
|
|
|
return decl->getTemplateParameterList(0)->getTemplateLoc();
|
2021-01-25 10:09:56 +00:00
|
|
|
return decl->getInnerLocStart();
|
2010-07-06 18:42:40 +00:00
|
|
|
}
|
|
|
|
|
2009-08-21 00:31:54 +00:00
|
|
|
SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
|
2010-05-28 23:32:21 +00:00
|
|
|
TypeSourceInfo *TSI = getTypeSourceInfo();
|
|
|
|
if (TSI) return TSI->getTypeLoc().getBeginLoc();
|
2009-08-21 00:31:54 +00:00
|
|
|
return SourceLocation();
|
|
|
|
}
|
|
|
|
|
2020-01-01 16:23:19 +00:00
|
|
|
SourceLocation DeclaratorDecl::getTypeSpecEndLoc() const {
|
|
|
|
TypeSourceInfo *TSI = getTypeSourceInfo();
|
|
|
|
if (TSI) return TSI->getTypeLoc().getEndLoc();
|
|
|
|
return SourceLocation();
|
|
|
|
}
|
|
|
|
|
2011-02-25 02:25:35 +00:00
|
|
|
void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
|
|
|
|
if (QualifierLoc) {
|
2010-03-15 10:12:16 +00:00
|
|
|
// Make sure the extended decl info is allocated.
|
|
|
|
if (!hasExtInfo()) {
|
|
|
|
// Save (non-extended) type source info pointer.
|
2015-11-09 17:53:06 +00:00
|
|
|
auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
|
2010-03-15 10:12:16 +00:00
|
|
|
// Allocate external info struct.
|
|
|
|
DeclInfo = new (getASTContext()) ExtInfo;
|
|
|
|
// Restore savedTInfo into (extended) decl info.
|
|
|
|
getExtInfo()->TInfo = savedTInfo;
|
|
|
|
}
|
|
|
|
// Set qualifier info.
|
2011-02-25 02:25:35 +00:00
|
|
|
getExtInfo()->QualifierLoc = QualifierLoc;
|
2020-01-09 13:07:51 +00:00
|
|
|
} else if (hasExtInfo()) {
|
2010-03-15 10:12:16 +00:00
|
|
|
// Here Qualifier == 0, i.e., we are removing the qualifier (if any).
|
2020-01-09 13:07:51 +00:00
|
|
|
getExtInfo()->QualifierLoc = QualifierLoc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) {
|
|
|
|
assert(TrailingRequiresClause);
|
|
|
|
// Make sure the extended decl info is allocated.
|
|
|
|
if (!hasExtInfo()) {
|
|
|
|
// Save (non-extended) type source info pointer.
|
|
|
|
auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
|
|
|
|
// Allocate external info struct.
|
|
|
|
DeclInfo = new (getASTContext()) ExtInfo;
|
|
|
|
// Restore savedTInfo into (extended) decl info.
|
|
|
|
getExtInfo()->TInfo = savedTInfo;
|
2010-03-15 10:12:16 +00:00
|
|
|
}
|
2020-01-09 13:07:51 +00:00
|
|
|
// Set requires clause info.
|
|
|
|
getExtInfo()->TrailingRequiresClause = TrailingRequiresClause;
|
2010-03-15 10:12:16 +00:00
|
|
|
}
|
|
|
|
|
2015-08-05 09:40:49 +00:00
|
|
|
void DeclaratorDecl::setTemplateParameterListsInfo(
|
|
|
|
ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
|
|
|
|
assert(!TPLists.empty());
|
2011-03-18 15:16:37 +00:00
|
|
|
// Make sure the extended decl info is allocated.
|
|
|
|
if (!hasExtInfo()) {
|
|
|
|
// Save (non-extended) type source info pointer.
|
2015-11-09 17:53:06 +00:00
|
|
|
auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
|
2011-03-18 15:16:37 +00:00
|
|
|
// Allocate external info struct.
|
|
|
|
DeclInfo = new (getASTContext()) ExtInfo;
|
|
|
|
// Restore savedTInfo into (extended) decl info.
|
|
|
|
getExtInfo()->TInfo = savedTInfo;
|
|
|
|
}
|
|
|
|
// Set the template parameter lists info.
|
2015-08-05 09:40:49 +00:00
|
|
|
getExtInfo()->setTemplateParameterListsInfo(Context, TPLists);
|
2011-03-18 15:16:37 +00:00
|
|
|
}
|
|
|
|
|
2010-07-06 18:42:40 +00:00
|
|
|
SourceLocation DeclaratorDecl::getOuterLocStart() const {
|
|
|
|
return getTemplateOrInnerLocStart(this);
|
|
|
|
}
|
|
|
|
|
2011-03-08 16:41:52 +00:00
|
|
|
// Helper function: returns true if QT is or contains a type
|
|
|
|
// having a postfix component.
|
2017-11-13 23:01:27 +00:00
|
|
|
static bool typeIsPostfix(QualType QT) {
|
2011-03-08 16:41:52 +00:00
|
|
|
while (true) {
|
|
|
|
const Type* T = QT.getTypePtr();
|
|
|
|
switch (T->getTypeClass()) {
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
case Type::Pointer:
|
|
|
|
QT = cast<PointerType>(T)->getPointeeType();
|
|
|
|
break;
|
|
|
|
case Type::BlockPointer:
|
|
|
|
QT = cast<BlockPointerType>(T)->getPointeeType();
|
|
|
|
break;
|
|
|
|
case Type::MemberPointer:
|
|
|
|
QT = cast<MemberPointerType>(T)->getPointeeType();
|
|
|
|
break;
|
|
|
|
case Type::LValueReference:
|
|
|
|
case Type::RValueReference:
|
|
|
|
QT = cast<ReferenceType>(T)->getPointeeType();
|
|
|
|
break;
|
|
|
|
case Type::PackExpansion:
|
|
|
|
QT = cast<PackExpansionType>(T)->getPattern();
|
|
|
|
break;
|
|
|
|
case Type::Paren:
|
|
|
|
case Type::ConstantArray:
|
|
|
|
case Type::DependentSizedArray:
|
|
|
|
case Type::IncompleteArray:
|
|
|
|
case Type::VariableArray:
|
|
|
|
case Type::FunctionProto:
|
|
|
|
case Type::FunctionNoProto:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceRange DeclaratorDecl::getSourceRange() const {
|
|
|
|
SourceLocation RangeEnd = getLocation();
|
|
|
|
if (TypeSourceInfo *TInfo = getTypeSourceInfo()) {
|
2014-02-02 15:28:46 +00:00
|
|
|
// If the declaration has no name or the type extends past the name take the
|
|
|
|
// end location of the type.
|
|
|
|
if (!getDeclName() || typeIsPostfix(TInfo->getType()))
|
2011-03-08 16:41:52 +00:00
|
|
|
RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd();
|
|
|
|
}
|
|
|
|
return SourceRange(getOuterLocStart(), RangeEnd);
|
|
|
|
}
|
|
|
|
|
2015-08-05 09:40:49 +00:00
|
|
|
void QualifierInfo::setTemplateParameterListsInfo(
|
|
|
|
ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
|
2010-06-12 08:15:14 +00:00
|
|
|
// Free previous template parameters (if any).
|
|
|
|
if (NumTemplParamLists > 0) {
|
2010-06-15 17:44:38 +00:00
|
|
|
Context.Deallocate(TemplParamLists);
|
2014-05-12 05:36:57 +00:00
|
|
|
TemplParamLists = nullptr;
|
2010-06-12 08:15:14 +00:00
|
|
|
NumTemplParamLists = 0;
|
|
|
|
}
|
|
|
|
// Set info on matched template parameter lists (if any).
|
2015-08-05 09:40:49 +00:00
|
|
|
if (!TPLists.empty()) {
|
|
|
|
TemplParamLists = new (Context) TemplateParameterList *[TPLists.size()];
|
|
|
|
NumTemplParamLists = TPLists.size();
|
|
|
|
std::copy(TPLists.begin(), TPLists.end(), TemplParamLists);
|
2010-06-12 08:15:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-17 23:39:55 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// VarDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) {
|
|
|
|
switch (SC) {
|
2021-01-04 22:17:45 +00:00
|
|
|
case SC_None: break;
|
|
|
|
case SC_Auto: return "auto";
|
|
|
|
case SC_Extern: return "extern";
|
|
|
|
case SC_PrivateExtern: return "__private_extern__";
|
|
|
|
case SC_Register: return "register";
|
|
|
|
case SC_Static: return "static";
|
2010-01-26 22:01:41 +00:00
|
|
|
}
|
|
|
|
|
2011-09-20 12:40:26 +00:00
|
|
|
llvm_unreachable("Invalid storage class");
|
2010-01-26 22:01:41 +00:00
|
|
|
}
|
|
|
|
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-16 23:01:30 +00:00
|
|
|
VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation StartLoc, SourceLocation IdLoc,
|
2022-03-23 15:03:44 +00:00
|
|
|
const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-16 23:01:30 +00:00
|
|
|
StorageClass SC)
|
|
|
|
: DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
|
2017-11-13 23:01:27 +00:00
|
|
|
redeclarable_base(C) {
|
2014-03-15 18:54:13 +00:00
|
|
|
static_assert(sizeof(VarDeclBitfields) <= sizeof(unsigned),
|
|
|
|
"VarDeclBitfields too large!");
|
|
|
|
static_assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned),
|
|
|
|
"ParmVarDeclBitfields too large!");
|
2015-05-19 00:57:16 +00:00
|
|
|
static_assert(sizeof(NonParmVarDeclBitfields) <= sizeof(unsigned),
|
|
|
|
"NonParmVarDeclBitfields too large!");
|
2013-08-06 01:03:05 +00:00
|
|
|
AllBits = 0;
|
2021-01-04 22:17:45 +00:00
|
|
|
VarDeclBits.SClass = SC;
|
2013-08-06 01:03:05 +00:00
|
|
|
// Everything else is implicitly initialized to false.
|
|
|
|
}
|
|
|
|
|
2022-03-23 15:03:44 +00:00
|
|
|
VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartL,
|
|
|
|
SourceLocation IdL, const IdentifierInfo *Id,
|
|
|
|
QualType T, TypeSourceInfo *TInfo, StorageClass S) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-16 23:01:30 +00:00
|
|
|
return new (C, DC) VarDecl(Var, C, DC, StartL, IdL, Id, T, TInfo, S);
|
2008-12-17 23:39:55 +00:00
|
|
|
}
|
|
|
|
|
2012-01-05 21:55:30 +00:00
|
|
|
VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-16 23:01:30 +00:00
|
|
|
return new (C, ID)
|
|
|
|
VarDecl(Var, C, nullptr, SourceLocation(), SourceLocation(), nullptr,
|
2021-01-04 22:17:45 +00:00
|
|
|
QualType(), nullptr, SC_None);
|
2012-01-05 21:55:30 +00:00
|
|
|
}
|
|
|
|
|
2010-12-06 18:36:25 +00:00
|
|
|
void VarDecl::setStorageClass(StorageClass SC) {
|
|
|
|
assert(isLegalForVariable(SC));
|
2021-01-04 22:17:45 +00:00
|
|
|
VarDeclBits.SClass = SC;
|
2010-12-06 18:36:25 +00:00
|
|
|
}
|
|
|
|
|
2014-05-01 03:16:47 +00:00
|
|
|
VarDecl::TLSKind VarDecl::getTLSKind() const {
|
|
|
|
switch (VarDeclBits.TSCSpec) {
|
|
|
|
case TSCS_unspecified:
|
2015-07-13 22:54:53 +00:00
|
|
|
if (!hasAttr<ThreadAttr>() &&
|
|
|
|
!(getASTContext().getLangOpts().OpenMPUseTLS &&
|
|
|
|
getASTContext().getTargetInfo().isTLSSupported() &&
|
|
|
|
hasAttr<OMPThreadPrivateDeclAttr>()))
|
2015-05-14 05:19:23 +00:00
|
|
|
return TLS_None;
|
2015-07-13 22:54:53 +00:00
|
|
|
return ((getASTContext().getLangOpts().isCompatibleWithMSVC(
|
|
|
|
LangOptions::MSVC2015)) ||
|
|
|
|
hasAttr<OMPThreadPrivateDeclAttr>())
|
2015-05-14 05:19:23 +00:00
|
|
|
? TLS_Dynamic
|
|
|
|
: TLS_Static;
|
2014-05-01 03:16:47 +00:00
|
|
|
case TSCS___thread: // Fall through.
|
|
|
|
case TSCS__Thread_local:
|
2015-07-13 22:54:53 +00:00
|
|
|
return TLS_Static;
|
2014-05-01 03:16:47 +00:00
|
|
|
case TSCS_thread_local:
|
|
|
|
return TLS_Dynamic;
|
|
|
|
}
|
|
|
|
llvm_unreachable("Unknown thread storage class specifier!");
|
|
|
|
}
|
|
|
|
|
2010-07-06 18:42:40 +00:00
|
|
|
SourceRange VarDecl::getSourceRange() const {
|
2012-10-08 23:08:41 +00:00
|
|
|
if (const Expr *Init = getInit()) {
|
2018-08-09 21:09:38 +00:00
|
|
|
SourceLocation InitEnd = Init->getEndLoc();
|
2018-07-30 19:24:48 +00:00
|
|
|
// If Init is implicit, ignore its source range and fallback on
|
2013-01-22 17:00:09 +00:00
|
|
|
// DeclaratorDecl::getSourceRange() to handle postfix elements.
|
|
|
|
if (InitEnd.isValid() && InitEnd != getLocation())
|
2012-10-08 23:08:41 +00:00
|
|
|
return SourceRange(getOuterLocStart(), InitEnd);
|
|
|
|
}
|
2011-03-08 16:41:52 +00:00
|
|
|
return DeclaratorDecl::getSourceRange();
|
2009-06-20 08:09:14 +00:00
|
|
|
}
|
|
|
|
|
2013-01-04 21:18:45 +00:00
|
|
|
template<typename T>
|
2014-05-31 06:11:02 +00:00
|
|
|
static LanguageLinkage getDeclLanguageLinkage(const T &D) {
|
2013-02-14 01:47:04 +00:00
|
|
|
// C++ [dcl.link]p1: All function types, function names with external linkage,
|
|
|
|
// and variable names with external linkage have a language linkage.
|
2013-05-13 00:12:11 +00:00
|
|
|
if (!D.hasExternalFormalLinkage())
|
2013-02-14 01:47:04 +00:00
|
|
|
return NoLanguageLinkage;
|
|
|
|
|
|
|
|
// Language linkage is a C++ concept, but saying that everything else in C has
|
2013-01-04 20:41:40 +00:00
|
|
|
// C language linkage fits the implementation nicely.
|
2012-12-28 14:21:58 +00:00
|
|
|
ASTContext &Context = D.getASTContext();
|
|
|
|
if (!Context.getLangOpts().CPlusPlus)
|
2013-02-14 01:18:37 +00:00
|
|
|
return CLanguageLinkage;
|
|
|
|
|
2013-02-14 01:47:04 +00:00
|
|
|
// C++ [dcl.link]p4: A C language linkage is ignored in determining the
|
|
|
|
// language linkage of the names of class members and the function type of
|
|
|
|
// class member functions.
|
2012-12-28 14:21:58 +00:00
|
|
|
const DeclContext *DC = D.getDeclContext();
|
|
|
|
if (DC->isRecord())
|
2013-02-14 01:18:37 +00:00
|
|
|
return CXXLanguageLinkage;
|
2012-12-28 14:21:58 +00:00
|
|
|
|
|
|
|
// If the first decl is in an extern "C" context, any other redeclaration
|
|
|
|
// will have C language linkage. If the first one is not in an extern "C"
|
|
|
|
// context, we would have reported an error for any other decl being in one.
|
2013-05-05 20:15:21 +00:00
|
|
|
if (isFirstInExternCContext(&D))
|
2013-02-14 01:18:37 +00:00
|
|
|
return CLanguageLinkage;
|
|
|
|
return CXXLanguageLinkage;
|
2012-12-28 14:21:58 +00:00
|
|
|
}
|
|
|
|
|
2013-03-14 03:07:35 +00:00
|
|
|
template<typename T>
|
2014-05-31 06:11:02 +00:00
|
|
|
static bool isDeclExternC(const T &D) {
|
2013-03-14 03:07:35 +00:00
|
|
|
// Since the context is ignored for class members, they can only have C++
|
|
|
|
// language linkage or no language linkage.
|
|
|
|
const DeclContext *DC = D.getDeclContext();
|
|
|
|
if (DC->isRecord()) {
|
|
|
|
assert(D.getASTContext().getLangOpts().CPlusPlus);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return D.getLanguageLinkage() == CLanguageLinkage;
|
|
|
|
}
|
|
|
|
|
2013-02-14 01:18:37 +00:00
|
|
|
LanguageLinkage VarDecl::getLanguageLinkage() const {
|
2014-05-31 06:11:02 +00:00
|
|
|
return getDeclLanguageLinkage(*this);
|
2012-12-28 14:21:58 +00:00
|
|
|
}
|
|
|
|
|
2013-03-14 03:07:35 +00:00
|
|
|
bool VarDecl::isExternC() const {
|
2014-05-31 06:11:02 +00:00
|
|
|
return isDeclExternC(*this);
|
2013-03-14 03:07:35 +00:00
|
|
|
}
|
|
|
|
|
2013-05-05 20:15:21 +00:00
|
|
|
bool VarDecl::isInExternCContext() const {
|
2013-11-14 02:13:03 +00:00
|
|
|
return getLexicalDeclContext()->isExternCContext();
|
2013-05-05 20:15:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool VarDecl::isInExternCXXContext() const {
|
2013-11-14 02:13:03 +00:00
|
|
|
return getLexicalDeclContext()->isExternCXXContext();
|
2013-05-05 20:15:21 +00:00
|
|
|
}
|
|
|
|
|
2013-10-17 15:37:26 +00:00
|
|
|
VarDecl *VarDecl::getCanonicalDecl() { return getFirstDecl(); }
|
2010-01-26 22:01:41 +00:00
|
|
|
|
2015-04-15 21:53:00 +00:00
|
|
|
VarDecl::DefinitionKind
|
|
|
|
VarDecl::isThisDeclarationADefinition(ASTContext &C) const {
|
2017-12-02 00:55:48 +00:00
|
|
|
if (isThisDeclarationADemotedDefinition())
|
|
|
|
return DeclarationOnly;
|
|
|
|
|
2010-01-31 22:27:38 +00:00
|
|
|
// C++ [basic.def]p2:
|
|
|
|
// A declaration is a definition unless [...] it contains the 'extern'
|
|
|
|
// specifier or a linkage-specification and neither an initializer [...],
|
2016-06-25 00:15:56 +00:00
|
|
|
// it declares a non-inline static data member in a class declaration [...],
|
|
|
|
// it declares a static data member outside a class definition and the variable
|
|
|
|
// was defined within the class with the constexpr specifier [...],
|
2013-09-27 20:14:12 +00:00
|
|
|
// C++1y [temp.expl.spec]p15:
|
|
|
|
// An explicit specialization of a static data member or an explicit
|
|
|
|
// specialization of a static data member template is a definition if the
|
|
|
|
// declaration includes an initializer; otherwise, it is a declaration.
|
|
|
|
//
|
|
|
|
// FIXME: How do you declare (but not define) a partial specialization of
|
|
|
|
// a static data member template outside the containing class?
|
2010-01-31 22:27:38 +00:00
|
|
|
if (isStaticDataMember()) {
|
2013-09-27 20:14:12 +00:00
|
|
|
if (isOutOfLine() &&
|
2016-06-25 00:15:56 +00:00
|
|
|
!(getCanonicalDecl()->isInline() &&
|
|
|
|
getCanonicalDecl()->isConstexpr()) &&
|
2013-09-27 20:14:12 +00:00
|
|
|
(hasInit() ||
|
|
|
|
// If the first declaration is out-of-line, this may be an
|
|
|
|
// instantiation of an out-of-line partial specialization of a variable
|
|
|
|
// template for which we have not yet instantiated the initializer.
|
2013-10-17 15:37:26 +00:00
|
|
|
(getFirstDecl()->isOutOfLine()
|
2013-09-27 20:14:12 +00:00
|
|
|
? getTemplateSpecializationKind() == TSK_Undeclared
|
|
|
|
: getTemplateSpecializationKind() !=
|
|
|
|
TSK_ExplicitSpecialization) ||
|
|
|
|
isa<VarTemplatePartialSpecializationDecl>(this)))
|
2010-01-31 22:27:38 +00:00
|
|
|
return Definition;
|
2021-01-25 10:09:56 +00:00
|
|
|
if (!isOutOfLine() && isInline())
|
2016-06-25 00:15:56 +00:00
|
|
|
return Definition;
|
2021-01-25 10:09:56 +00:00
|
|
|
return DeclarationOnly;
|
2010-01-31 22:27:38 +00:00
|
|
|
}
|
|
|
|
// 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;
|
2013-04-25 12:11:36 +00:00
|
|
|
|
2016-04-11 07:48:59 +00:00
|
|
|
if (hasDefiningAttr())
|
2013-10-22 21:39:03 +00:00
|
|
|
return Definition;
|
|
|
|
|
2015-05-14 05:19:20 +00:00
|
|
|
if (const auto *SAA = getAttr<SelectAnyAttr>())
|
|
|
|
if (!SAA->isInherited())
|
|
|
|
return Definition;
|
|
|
|
|
2013-09-27 20:14:12 +00:00
|
|
|
// A variable template specialization (other than a static data member
|
|
|
|
// template or an explicit specialization) is a declaration until we
|
|
|
|
// instantiate its initializer.
|
2017-12-02 02:48:42 +00:00
|
|
|
if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(this)) {
|
|
|
|
if (VTSD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization &&
|
|
|
|
!isa<VarTemplatePartialSpecializationDecl>(VTSD) &&
|
|
|
|
!VTSD->IsCompleteDefinition)
|
|
|
|
return DeclarationOnly;
|
|
|
|
}
|
2013-09-27 20:14:12 +00:00
|
|
|
|
2015-04-15 23:04:24 +00:00
|
|
|
if (hasExternalStorage())
|
2010-01-31 22:27:38 +00:00
|
|
|
return DeclarationOnly;
|
2013-03-07 01:42:44 +00:00
|
|
|
|
2013-04-25 12:11:36 +00:00
|
|
|
// [dcl.link] p7:
|
|
|
|
// A declaration directly contained in a linkage-specification is treated
|
|
|
|
// as if it contains the extern specifier for the purpose of determining
|
|
|
|
// the linkage of the declared name and whether it is a definition.
|
2015-04-15 23:04:24 +00:00
|
|
|
if (isSingleLineLanguageLinkage(*this))
|
2013-04-26 01:30:23 +00:00
|
|
|
return DeclarationOnly;
|
2013-04-25 12:11:36 +00:00
|
|
|
|
2010-01-31 22:27:38 +00:00
|
|
|
// 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++.
|
2012-03-11 07:00:24 +00:00
|
|
|
if (!C.getLangOpts().CPlusPlus && isFileVarDecl())
|
2010-01-31 22:27:38 +00:00
|
|
|
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)
|
2014-05-12 05:36:57 +00:00
|
|
|
return nullptr;
|
2010-01-31 22:27:38 +00:00
|
|
|
|
2014-05-12 05:36:57 +00:00
|
|
|
VarDecl *LastTentative = nullptr;
|
2021-08-15 18:12:21 +00:00
|
|
|
|
|
|
|
// Loop through the declaration chain, starting with the most recent.
|
|
|
|
for (VarDecl *Decl = getMostRecentDecl(); Decl;
|
|
|
|
Decl = Decl->getPreviousDecl()) {
|
|
|
|
Kind = Decl->isThisDeclarationADefinition();
|
2010-01-31 22:27:38 +00:00
|
|
|
if (Kind == Definition)
|
2014-05-12 05:36:57 +00:00
|
|
|
return nullptr;
|
2021-08-15 18:12:21 +00:00
|
|
|
// Record the first (most recent) TentativeDefinition that is encountered.
|
|
|
|
if (Kind == TentativeDefinition && !LastTentative)
|
|
|
|
LastTentative = Decl;
|
2010-01-31 22:27:38 +00:00
|
|
|
}
|
2021-08-15 18:12:21 +00:00
|
|
|
|
2010-01-31 22:27:38 +00:00
|
|
|
return LastTentative;
|
|
|
|
}
|
|
|
|
|
2012-03-09 01:51:51 +00:00
|
|
|
VarDecl *VarDecl::getDefinition(ASTContext &C) {
|
2013-10-17 15:37:26 +00:00
|
|
|
VarDecl *First = getFirstDecl();
|
2022-09-04 06:27:27 +00:00
|
|
|
for (auto *I : First->redecls()) {
|
2014-03-06 23:45:36 +00:00
|
|
|
if (I->isThisDeclarationADefinition(C) == Definition)
|
|
|
|
return I;
|
2010-02-01 20:16:42 +00:00
|
|
|
}
|
2014-05-12 05:36:57 +00:00
|
|
|
return nullptr;
|
2010-01-31 22:27:38 +00:00
|
|
|
}
|
|
|
|
|
2012-03-09 01:51:51 +00:00
|
|
|
VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const {
|
2010-10-29 22:22:43 +00:00
|
|
|
DefinitionKind Kind = DeclarationOnly;
|
2015-11-09 17:53:06 +00:00
|
|
|
|
2013-10-17 15:37:26 +00:00
|
|
|
const VarDecl *First = getFirstDecl();
|
2022-09-04 06:27:27 +00:00
|
|
|
for (auto *I : First->redecls()) {
|
2014-03-06 23:45:36 +00:00
|
|
|
Kind = std::max(Kind, I->isThisDeclarationADefinition(C));
|
2012-03-06 23:52:46 +00:00
|
|
|
if (Kind == Definition)
|
|
|
|
break;
|
|
|
|
}
|
2010-10-29 22:22:43 +00:00
|
|
|
|
|
|
|
return Kind;
|
|
|
|
}
|
|
|
|
|
2010-02-01 20:16:42 +00:00
|
|
|
const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const {
|
2022-09-04 06:27:27 +00:00
|
|
|
for (auto *I : redecls()) {
|
2014-03-06 23:45:36 +00:00
|
|
|
if (auto Expr = I->getInit()) {
|
|
|
|
D = I;
|
|
|
|
return Expr;
|
|
|
|
}
|
2010-01-26 22:01:41 +00:00
|
|
|
}
|
2014-05-12 05:36:57 +00:00
|
|
|
return nullptr;
|
2010-01-26 22:01:41 +00:00
|
|
|
}
|
|
|
|
|
2015-12-30 02:51:00 +00:00
|
|
|
bool VarDecl::hasInit() const {
|
|
|
|
if (auto *P = dyn_cast<ParmVarDecl>(this))
|
|
|
|
if (P->hasUnparsedDefaultArg() || P->hasUninstantiatedDefaultArg())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return !Init.isNull();
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr *VarDecl::getInit() {
|
|
|
|
if (!hasInit())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (auto *S = Init.dyn_cast<Stmt *>())
|
|
|
|
return cast<Expr>(S);
|
|
|
|
|
PR60985: Fix merging of lambda closure types across modules.
Previously, distinct lambdas would get merged, and multiple definitions
of the same lambda would not get merged, because we attempted to
identify lambdas by their ordinal position within their lexical
DeclContext. This failed for lambdas within namespace-scope variables
and within variable templates, where the lexical position in the context
containing the variable didn't uniquely identify the lambda.
In this patch, we instead identify lambda closure types by index within
their context declaration, which does uniquely identify them in a way
that's consistent across modules.
This change causes a deserialization cycle between the type of a
variable with deduced type and a lambda appearing as the initializer of
the variable -- reading the variable's type requires reading and merging
the lambda, and reading the lambda requires reading and merging the
variable. This is addressed by deferring loading the deduced type of a
variable until after we finish recursive deserialization.
This also exposes a pre-existing subtle issue where loading a
variable declaration would trigger immediate loading of its initializer,
which could recursively refer back to properties of the variable. This
particularly causes problems if the initializer contains a
lambda-expression, but can be problematic in general. That is addressed
by switching to lazily loading the initializers of variables rather than
always loading them with the variable declaration. As well as fixing a
deserialization cycle, that should improve laziness of deserialization
in general.
LambdaDefinitionData had 63 spare bits in it, presumably caused by an
off-by-one-error in some previous change. This change claims 32 of those bits
as a counter for the lambda within its context. We could probably move the
numbering to separate storage, like we do for the device-side mangling number,
to optimize the likely-common case where all three numbers (host-side mangling
number, device-side mangling number, and index within the context declaration)
are zero, but that's not done in this change.
Fixes #60985.
Reviewed By: #clang-language-wg, aaron.ballman
Differential Revision: https://reviews.llvm.org/D145737
2023-03-30 21:21:31 +00:00
|
|
|
auto *Eval = getEvaluatedStmt();
|
|
|
|
return cast<Expr>(Eval->Value.isOffset()
|
|
|
|
? Eval->Value.get(getASTContext().getExternalSource())
|
|
|
|
: Eval->Value.get(nullptr));
|
2015-12-30 02:51:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Stmt **VarDecl::getInitAddress() {
|
|
|
|
if (auto *ES = Init.dyn_cast<EvaluatedStmt *>())
|
PR60985: Fix merging of lambda closure types across modules.
Previously, distinct lambdas would get merged, and multiple definitions
of the same lambda would not get merged, because we attempted to
identify lambdas by their ordinal position within their lexical
DeclContext. This failed for lambdas within namespace-scope variables
and within variable templates, where the lexical position in the context
containing the variable didn't uniquely identify the lambda.
In this patch, we instead identify lambda closure types by index within
their context declaration, which does uniquely identify them in a way
that's consistent across modules.
This change causes a deserialization cycle between the type of a
variable with deduced type and a lambda appearing as the initializer of
the variable -- reading the variable's type requires reading and merging
the lambda, and reading the lambda requires reading and merging the
variable. This is addressed by deferring loading the deduced type of a
variable until after we finish recursive deserialization.
This also exposes a pre-existing subtle issue where loading a
variable declaration would trigger immediate loading of its initializer,
which could recursively refer back to properties of the variable. This
particularly causes problems if the initializer contains a
lambda-expression, but can be problematic in general. That is addressed
by switching to lazily loading the initializers of variables rather than
always loading them with the variable declaration. As well as fixing a
deserialization cycle, that should improve laziness of deserialization
in general.
LambdaDefinitionData had 63 spare bits in it, presumably caused by an
off-by-one-error in some previous change. This change claims 32 of those bits
as a counter for the lambda within its context. We could probably move the
numbering to separate storage, like we do for the device-side mangling number,
to optimize the likely-common case where all three numbers (host-side mangling
number, device-side mangling number, and index within the context declaration)
are zero, but that's not done in this change.
Fixes #60985.
Reviewed By: #clang-language-wg, aaron.ballman
Differential Revision: https://reviews.llvm.org/D145737
2023-03-30 21:21:31 +00:00
|
|
|
return ES->Value.getAddressOfPointer(getASTContext().getExternalSource());
|
2015-12-30 02:51:00 +00:00
|
|
|
|
|
|
|
return Init.getAddrOfPtr1();
|
|
|
|
}
|
|
|
|
|
2019-09-04 20:30:37 +00:00
|
|
|
VarDecl *VarDecl::getInitializingDeclaration() {
|
|
|
|
VarDecl *Def = nullptr;
|
2022-09-04 06:27:27 +00:00
|
|
|
for (auto *I : redecls()) {
|
2019-09-04 20:30:37 +00:00
|
|
|
if (I->hasInit())
|
|
|
|
return I;
|
|
|
|
|
|
|
|
if (I->isThisDeclarationADefinition()) {
|
|
|
|
if (isStaticDataMember())
|
|
|
|
return I;
|
2021-01-25 10:09:56 +00:00
|
|
|
Def = I;
|
2019-09-04 20:30:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return Def;
|
|
|
|
}
|
|
|
|
|
2009-10-14 21:29:40 +00:00
|
|
|
bool VarDecl::isOutOfLine() const {
|
2011-02-19 18:51:44 +00:00
|
|
|
if (Decl::isOutOfLine())
|
2009-10-14 21:29:40 +00:00
|
|
|
return true;
|
2010-02-21 07:08:09 +00:00
|
|
|
|
|
|
|
if (!isStaticDataMember())
|
|
|
|
return false;
|
|
|
|
|
2009-10-14 21:29:40 +00:00
|
|
|
// If this static data member was instantiated from a static data member of
|
2018-07-30 19:24:48 +00:00
|
|
|
// a class template, check whether that static data member was defined
|
2009-10-14 21:29:40 +00:00
|
|
|
// out-of-line.
|
|
|
|
if (VarDecl *VD = getInstantiatedFromStaticDataMember())
|
|
|
|
return VD->isOutOfLine();
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2009-10-14 21:29:40 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-02-11 01:19:42 +00:00
|
|
|
void VarDecl::setInit(Expr *I) {
|
2015-11-09 17:53:06 +00:00
|
|
|
if (auto *Eval = Init.dyn_cast<EvaluatedStmt *>()) {
|
2010-01-26 22:01:41 +00:00
|
|
|
Eval->~EvaluatedStmt();
|
2010-02-11 01:19:42 +00:00
|
|
|
getASTContext().Deallocate(Eval);
|
2010-01-26 22:01:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Init = I;
|
|
|
|
}
|
|
|
|
|
2020-10-26 19:08:57 +00:00
|
|
|
bool VarDecl::mightBeUsableInConstantExpressions(const ASTContext &C) const {
|
2012-03-11 07:00:24 +00:00
|
|
|
const LangOptions &Lang = C.getLangOpts();
|
2011-12-21 02:55:12 +00:00
|
|
|
|
2020-10-16 00:50:48 +00:00
|
|
|
// OpenCL permits const integral variables to be used in constant
|
|
|
|
// expressions, like in C++98.
|
|
|
|
if (!Lang.CPlusPlus && !Lang.OpenCL)
|
2012-03-02 04:14:40 +00:00
|
|
|
return false;
|
|
|
|
|
2019-06-11 17:50:32 +00:00
|
|
|
// Function parameters are never usable in constant expressions.
|
|
|
|
if (isa<ParmVarDecl>(this))
|
|
|
|
return false;
|
|
|
|
|
2020-09-30 17:48:00 +00:00
|
|
|
// The values of weak variables are never usable in constant expressions.
|
|
|
|
if (isWeak())
|
|
|
|
return false;
|
|
|
|
|
2012-03-02 04:14:40 +00:00
|
|
|
// In C++11, any variable of reference type can be used in a constant
|
|
|
|
// expression if it is initialized by a constant expression.
|
2013-01-02 11:42:31 +00:00
|
|
|
if (Lang.CPlusPlus11 && getType()->isReferenceType())
|
2012-03-02 04:14:40 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
// Only const objects can be used in constant expressions in C++. C++98 does
|
2011-12-21 02:55:12 +00:00
|
|
|
// not require the variable to be non-volatile, but we consider this to be a
|
|
|
|
// defect.
|
2020-10-16 00:50:48 +00:00
|
|
|
if (!getType().isConstant(C) || getType().isVolatileQualified())
|
2011-12-21 02:55:12 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// In C++, const, non-volatile variables of integral or enumeration types
|
|
|
|
// can be used in constant expressions.
|
|
|
|
if (getType()->isIntegralOrEnumerationType())
|
|
|
|
return true;
|
|
|
|
|
2012-03-02 04:14:40 +00:00
|
|
|
// Additionally, in C++11, non-volatile constexpr variables can be used in
|
|
|
|
// constant expressions.
|
2013-01-02 11:42:31 +00:00
|
|
|
return Lang.CPlusPlus11 && isConstexpr();
|
2011-12-21 02:55:12 +00:00
|
|
|
}
|
|
|
|
|
2020-10-26 19:08:57 +00:00
|
|
|
bool VarDecl::isUsableInConstantExpressions(const ASTContext &Context) const {
|
2019-06-11 17:50:32 +00:00
|
|
|
// C++2a [expr.const]p3:
|
|
|
|
// A variable is usable in constant expressions after its initializing
|
|
|
|
// declaration is encountered...
|
|
|
|
const VarDecl *DefVD = nullptr;
|
|
|
|
const Expr *Init = getAnyInitializer(DefVD);
|
2019-06-17 21:46:17 +00:00
|
|
|
if (!Init || Init->isValueDependent() || getType()->isDependentType())
|
2019-06-11 17:50:32 +00:00
|
|
|
return false;
|
|
|
|
// ... if it is a constexpr variable, or it is of reference type or of
|
|
|
|
// const-qualified integral or enumeration type, ...
|
|
|
|
if (!DefVD->mightBeUsableInConstantExpressions(Context))
|
|
|
|
return false;
|
|
|
|
// ... and its initializer is a constant initializer.
|
2020-10-16 00:50:48 +00:00
|
|
|
if (Context.getLangOpts().CPlusPlus && !DefVD->hasConstantInitialization())
|
2020-10-20 04:29:13 +00:00
|
|
|
return false;
|
|
|
|
// C++98 [expr.const]p1:
|
|
|
|
// An integral constant-expression can involve only [...] const variables
|
|
|
|
// or static data members of integral or enumeration types initialized with
|
|
|
|
// [integer] constant expressions (dcl.init)
|
2020-10-16 00:50:48 +00:00
|
|
|
if ((Context.getLangOpts().CPlusPlus || Context.getLangOpts().OpenCL) &&
|
|
|
|
!Context.getLangOpts().CPlusPlus11 && !DefVD->hasICEInitializer(Context))
|
2020-10-20 04:29:13 +00:00
|
|
|
return false;
|
|
|
|
return true;
|
2019-06-11 17:50:32 +00:00
|
|
|
}
|
|
|
|
|
2011-12-19 06:19:21 +00:00
|
|
|
/// Convert the initializer for this declaration to the elaborated EvaluatedStmt
|
|
|
|
/// form, which contains extra information on the evaluated value of the
|
|
|
|
/// initializer.
|
|
|
|
EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const {
|
2015-11-09 17:53:06 +00:00
|
|
|
auto *Eval = Init.dyn_cast<EvaluatedStmt *>();
|
2011-12-19 06:19:21 +00:00
|
|
|
if (!Eval) {
|
2013-06-03 13:51:33 +00:00
|
|
|
// Note: EvaluatedStmt contains an APValue, which usually holds
|
|
|
|
// resources not allocated from the ASTContext. We need to do some
|
|
|
|
// work to avoid leaking those, but we do so in VarDecl::evaluateValue
|
|
|
|
// where we can detect whether there's anything to clean up or not.
|
2011-12-19 06:19:21 +00:00
|
|
|
Eval = new (getASTContext()) EvaluatedStmt;
|
2015-12-30 02:51:00 +00:00
|
|
|
Eval->Value = Init.get<Stmt *>();
|
2011-12-19 06:19:21 +00:00
|
|
|
Init = Eval;
|
|
|
|
}
|
|
|
|
return Eval;
|
|
|
|
}
|
|
|
|
|
2020-10-26 19:08:57 +00:00
|
|
|
EvaluatedStmt *VarDecl::getEvaluatedStmt() const {
|
|
|
|
return Init.dyn_cast<EvaluatedStmt *>();
|
|
|
|
}
|
|
|
|
|
2012-01-14 04:30:29 +00:00
|
|
|
APValue *VarDecl::evaluateValue() const {
|
2013-01-12 19:30:44 +00:00
|
|
|
SmallVector<PartialDiagnosticAt, 8> Notes;
|
2020-10-20 03:03:18 +00:00
|
|
|
return evaluateValueImpl(Notes, hasConstantInitialization());
|
2012-01-14 04:30:29 +00:00
|
|
|
}
|
|
|
|
|
2020-10-20 03:03:18 +00:00
|
|
|
APValue *VarDecl::evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> &Notes,
|
|
|
|
bool IsConstantInitialization) const {
|
2011-12-19 06:19:21 +00:00
|
|
|
EvaluatedStmt *Eval = ensureEvaluatedStmt();
|
|
|
|
|
PR60985: Fix merging of lambda closure types across modules.
Previously, distinct lambdas would get merged, and multiple definitions
of the same lambda would not get merged, because we attempted to
identify lambdas by their ordinal position within their lexical
DeclContext. This failed for lambdas within namespace-scope variables
and within variable templates, where the lexical position in the context
containing the variable didn't uniquely identify the lambda.
In this patch, we instead identify lambda closure types by index within
their context declaration, which does uniquely identify them in a way
that's consistent across modules.
This change causes a deserialization cycle between the type of a
variable with deduced type and a lambda appearing as the initializer of
the variable -- reading the variable's type requires reading and merging
the lambda, and reading the lambda requires reading and merging the
variable. This is addressed by deferring loading the deduced type of a
variable until after we finish recursive deserialization.
This also exposes a pre-existing subtle issue where loading a
variable declaration would trigger immediate loading of its initializer,
which could recursively refer back to properties of the variable. This
particularly causes problems if the initializer contains a
lambda-expression, but can be problematic in general. That is addressed
by switching to lazily loading the initializers of variables rather than
always loading them with the variable declaration. As well as fixing a
deserialization cycle, that should improve laziness of deserialization
in general.
LambdaDefinitionData had 63 spare bits in it, presumably caused by an
off-by-one-error in some previous change. This change claims 32 of those bits
as a counter for the lambda within its context. We could probably move the
numbering to separate storage, like we do for the device-side mangling number,
to optimize the likely-common case where all three numbers (host-side mangling
number, device-side mangling number, and index within the context declaration)
are zero, but that's not done in this change.
Fixes #60985.
Reviewed By: #clang-language-wg, aaron.ballman
Differential Revision: https://reviews.llvm.org/D145737
2023-03-30 21:21:31 +00:00
|
|
|
const auto *Init = getInit();
|
2020-10-26 19:08:57 +00:00
|
|
|
assert(!Init->isValueDependent());
|
|
|
|
|
2011-12-19 06:19:21 +00:00
|
|
|
// We only produce notes indicating why an initializer is non-constant the
|
|
|
|
// first time it is evaluated. FIXME: The notes won't always be emitted the
|
|
|
|
// first time we try evaluation, so might not be produced at all.
|
|
|
|
if (Eval->WasEvaluated)
|
2019-05-21 23:15:18 +00:00
|
|
|
return Eval->Evaluated.isAbsent() ? nullptr : &Eval->Evaluated;
|
2011-12-19 06:19:21 +00:00
|
|
|
|
|
|
|
if (Eval->IsEvaluating) {
|
|
|
|
// FIXME: Produce a diagnostic for self-initialization.
|
2014-05-12 05:36:57 +00:00
|
|
|
return nullptr;
|
2011-12-19 06:19:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Eval->IsEvaluating = true;
|
|
|
|
|
2020-10-20 03:03:18 +00:00
|
|
|
ASTContext &Ctx = getASTContext();
|
|
|
|
bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, Ctx, this, Notes,
|
|
|
|
IsConstantInitialization);
|
|
|
|
|
2023-09-11 15:37:01 +00:00
|
|
|
// In C++, this isn't a constant initializer if we produced notes. In that
|
2020-10-20 03:03:18 +00:00
|
|
|
// case, we can't keep the result, because it may only be correct under the
|
|
|
|
// assumption that the initializer is a constant context.
|
2023-09-11 15:37:01 +00:00
|
|
|
if (IsConstantInitialization && Ctx.getLangOpts().CPlusPlus &&
|
2020-10-20 03:03:18 +00:00
|
|
|
!Notes.empty())
|
|
|
|
Result = false;
|
2011-12-19 06:19:21 +00:00
|
|
|
|
2013-06-03 13:51:33 +00:00
|
|
|
// Ensure the computed APValue is cleaned up later if evaluation succeeded,
|
|
|
|
// or that it's empty (so that there's nothing to clean up) if evaluation
|
|
|
|
// failed.
|
2011-12-19 06:19:21 +00:00
|
|
|
if (!Result)
|
|
|
|
Eval->Evaluated = APValue();
|
2013-06-03 13:51:33 +00:00
|
|
|
else if (Eval->Evaluated.needsCleanup())
|
2020-10-20 03:03:18 +00:00
|
|
|
Ctx.addDestruction(&Eval->Evaluated);
|
2011-12-19 06:19:21 +00:00
|
|
|
|
|
|
|
Eval->IsEvaluating = false;
|
|
|
|
Eval->WasEvaluated = true;
|
|
|
|
|
2014-05-12 05:36:57 +00:00
|
|
|
return Result ? &Eval->Evaluated : nullptr;
|
2011-12-19 06:19:21 +00:00
|
|
|
}
|
|
|
|
|
2015-12-30 02:51:00 +00:00
|
|
|
APValue *VarDecl::getEvaluatedValue() const {
|
2020-10-26 19:08:57 +00:00
|
|
|
if (EvaluatedStmt *Eval = getEvaluatedStmt())
|
2015-12-30 02:51:00 +00:00
|
|
|
if (Eval->WasEvaluated)
|
|
|
|
return &Eval->Evaluated;
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-10-20 04:29:13 +00:00
|
|
|
bool VarDecl::hasICEInitializer(const ASTContext &Context) const {
|
|
|
|
const Expr *Init = getInit();
|
|
|
|
assert(Init && "no initializer");
|
2015-12-30 02:51:00 +00:00
|
|
|
|
2020-10-20 04:29:13 +00:00
|
|
|
EvaluatedStmt *Eval = ensureEvaluatedStmt();
|
|
|
|
if (!Eval->CheckedForICEInit) {
|
|
|
|
Eval->CheckedForICEInit = true;
|
|
|
|
Eval->HasICEInit = Init->isIntegerConstantExpr(Context);
|
|
|
|
}
|
|
|
|
return Eval->HasICEInit;
|
2015-12-30 02:51:00 +00:00
|
|
|
}
|
|
|
|
|
2020-10-20 04:29:13 +00:00
|
|
|
bool VarDecl::hasConstantInitialization() const {
|
|
|
|
// In C, all globals (and only globals) have constant initialization.
|
|
|
|
if (hasGlobalStorage() && !getASTContext().getLangOpts().CPlusPlus)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// In C++, it depends on whether the evaluation at the point of definition
|
|
|
|
// was evaluatable as a constant initializer.
|
|
|
|
if (EvaluatedStmt *Eval = getEvaluatedStmt())
|
|
|
|
return Eval->HasConstantInitialization;
|
|
|
|
|
|
|
|
return false;
|
2015-12-30 02:51:00 +00:00
|
|
|
}
|
|
|
|
|
2020-10-20 04:29:13 +00:00
|
|
|
bool VarDecl::checkForConstantInitialization(
|
2020-10-20 02:01:48 +00:00
|
|
|
SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
|
2011-12-19 06:19:21 +00:00
|
|
|
EvaluatedStmt *Eval = ensureEvaluatedStmt();
|
2020-10-20 02:01:48 +00:00
|
|
|
// If we ask for the value before we know whether we have a constant
|
|
|
|
// initializer, we can compute the wrong value (for example, due to
|
|
|
|
// std::is_constant_evaluated()).
|
|
|
|
assert(!Eval->WasEvaluated &&
|
|
|
|
"already evaluated var value before checking for constant init");
|
2020-10-20 04:29:13 +00:00
|
|
|
assert(getASTContext().getLangOpts().CPlusPlus && "only meaningful in C++");
|
2011-12-19 06:19:21 +00:00
|
|
|
|
PR60985: Fix merging of lambda closure types across modules.
Previously, distinct lambdas would get merged, and multiple definitions
of the same lambda would not get merged, because we attempted to
identify lambdas by their ordinal position within their lexical
DeclContext. This failed for lambdas within namespace-scope variables
and within variable templates, where the lexical position in the context
containing the variable didn't uniquely identify the lambda.
In this patch, we instead identify lambda closure types by index within
their context declaration, which does uniquely identify them in a way
that's consistent across modules.
This change causes a deserialization cycle between the type of a
variable with deduced type and a lambda appearing as the initializer of
the variable -- reading the variable's type requires reading and merging
the lambda, and reading the lambda requires reading and merging the
variable. This is addressed by deferring loading the deduced type of a
variable until after we finish recursive deserialization.
This also exposes a pre-existing subtle issue where loading a
variable declaration would trigger immediate loading of its initializer,
which could recursively refer back to properties of the variable. This
particularly causes problems if the initializer contains a
lambda-expression, but can be problematic in general. That is addressed
by switching to lazily loading the initializers of variables rather than
always loading them with the variable declaration. As well as fixing a
deserialization cycle, that should improve laziness of deserialization
in general.
LambdaDefinitionData had 63 spare bits in it, presumably caused by an
off-by-one-error in some previous change. This change claims 32 of those bits
as a counter for the lambda within its context. We could probably move the
numbering to separate storage, like we do for the device-side mangling number,
to optimize the likely-common case where all three numbers (host-side mangling
number, device-side mangling number, and index within the context declaration)
are zero, but that's not done in this change.
Fixes #60985.
Reviewed By: #clang-language-wg, aaron.ballman
Differential Revision: https://reviews.llvm.org/D145737
2023-03-30 21:21:31 +00:00
|
|
|
assert(!getInit()->isValueDependent());
|
2011-12-19 06:19:21 +00:00
|
|
|
|
2020-10-20 04:29:13 +00:00
|
|
|
// Evaluate the initializer to check whether it's a constant expression.
|
2020-10-20 03:03:18 +00:00
|
|
|
Eval->HasConstantInitialization =
|
|
|
|
evaluateValueImpl(Notes, true) && Notes.empty();
|
|
|
|
|
|
|
|
// If evaluation as a constant initializer failed, allow re-evaluation as a
|
|
|
|
// non-constant initializer if we later find we want the value.
|
|
|
|
if (!Eval->HasConstantInitialization)
|
|
|
|
Eval->WasEvaluated = false;
|
|
|
|
|
2020-10-20 04:29:13 +00:00
|
|
|
return Eval->HasConstantInitialization;
|
2011-12-19 06:19:21 +00:00
|
|
|
}
|
|
|
|
|
2019-05-21 20:10:50 +00:00
|
|
|
bool VarDecl::isParameterPack() const {
|
|
|
|
return isa<PackExpansionType>(getType());
|
|
|
|
}
|
|
|
|
|
2017-04-21 01:15:13 +00:00
|
|
|
template<typename DeclT>
|
|
|
|
static DeclT *getDefinitionOrSelf(DeclT *D) {
|
|
|
|
assert(D);
|
|
|
|
if (auto *Def = D->getDefinition())
|
|
|
|
return Def;
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
2018-10-01 21:51:28 +00:00
|
|
|
bool VarDecl::isEscapingByref() const {
|
|
|
|
return hasAttr<BlocksAttr>() && NonParmVarDeclBits.EscapingByref;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool VarDecl::isNonEscapingByref() const {
|
|
|
|
return hasAttr<BlocksAttr>() && !NonParmVarDeclBits.EscapingByref;
|
|
|
|
}
|
|
|
|
|
2021-07-02 22:56:16 +00:00
|
|
|
bool VarDecl::hasDependentAlignment() const {
|
|
|
|
QualType T = getType();
|
2022-10-07 12:38:49 +00:00
|
|
|
return T->isDependentType() || T->isUndeducedType() ||
|
2021-07-02 22:56:16 +00:00
|
|
|
llvm::any_of(specific_attrs<AlignedAttr>(), [](const AlignedAttr *AA) {
|
|
|
|
return AA->isAlignmentDependent();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-10-14 21:41:24 +00:00
|
|
|
VarDecl *VarDecl::getTemplateInstantiationPattern() const {
|
2019-05-03 23:51:38 +00:00
|
|
|
const VarDecl *VD = this;
|
2016-10-14 21:41:24 +00:00
|
|
|
|
2019-05-03 23:51:38 +00:00
|
|
|
// If this is an instantiated member, walk back to the template from which
|
|
|
|
// it was instantiated.
|
|
|
|
if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo()) {
|
2016-10-14 21:41:24 +00:00
|
|
|
if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) {
|
2019-05-03 23:51:38 +00:00
|
|
|
VD = VD->getInstantiatedFromStaticDataMember();
|
2016-10-14 21:41:24 +00:00
|
|
|
while (auto *NewVD = VD->getInstantiatedFromStaticDataMember())
|
|
|
|
VD = NewVD;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-03 23:51:38 +00:00
|
|
|
// If it's an instantiated variable template specialization, find the
|
|
|
|
// template or partial specialization from which it was instantiated.
|
|
|
|
if (auto *VDTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(VD)) {
|
|
|
|
if (isTemplateInstantiation(VDTemplSpec->getTemplateSpecializationKind())) {
|
|
|
|
auto From = VDTemplSpec->getInstantiatedFrom();
|
|
|
|
if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) {
|
|
|
|
while (!VTD->isMemberSpecialization()) {
|
|
|
|
auto *NewVTD = VTD->getInstantiatedFromMemberTemplate();
|
|
|
|
if (!NewVTD)
|
|
|
|
break;
|
|
|
|
VTD = NewVTD;
|
|
|
|
}
|
|
|
|
return getDefinitionOrSelf(VTD->getTemplatedDecl());
|
|
|
|
}
|
|
|
|
if (auto *VTPSD =
|
|
|
|
From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
|
|
|
|
while (!VTPSD->isMemberSpecialization()) {
|
|
|
|
auto *NewVTPSD = VTPSD->getInstantiatedFromMember();
|
|
|
|
if (!NewVTPSD)
|
|
|
|
break;
|
|
|
|
VTPSD = NewVTPSD;
|
|
|
|
}
|
|
|
|
return getDefinitionOrSelf<VarDecl>(VTPSD);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this is the pattern of a variable template, find where it was
|
|
|
|
// instantiated from. FIXME: Is this necessary?
|
|
|
|
if (VarTemplateDecl *VarTemplate = VD->getDescribedVarTemplate()) {
|
|
|
|
while (!VarTemplate->isMemberSpecialization()) {
|
|
|
|
auto *NewVT = VarTemplate->getInstantiatedFromMemberTemplate();
|
|
|
|
if (!NewVT)
|
2016-10-14 21:41:24 +00:00
|
|
|
break;
|
2019-05-03 23:51:38 +00:00
|
|
|
VarTemplate = NewVT;
|
2016-10-14 21:41:24 +00:00
|
|
|
}
|
|
|
|
|
2017-04-21 01:15:13 +00:00
|
|
|
return getDefinitionOrSelf(VarTemplate->getTemplatedDecl());
|
2016-10-14 21:41:24 +00:00
|
|
|
}
|
2019-05-03 23:51:38 +00:00
|
|
|
|
|
|
|
if (VD == this)
|
|
|
|
return nullptr;
|
|
|
|
return getDefinitionOrSelf(const_cast<VarDecl*>(VD));
|
2016-10-14 21:41:24 +00:00
|
|
|
}
|
|
|
|
|
2009-10-14 21:29:40 +00:00
|
|
|
VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
|
2009-10-12 20:18:28 +00:00
|
|
|
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
|
2009-10-08 07:24:58 +00:00
|
|
|
return cast<VarDecl>(MSI->getInstantiatedFrom());
|
2014-05-12 05:36:57 +00:00
|
|
|
|
|
|
|
return nullptr;
|
2009-10-08 07:24:58 +00:00
|
|
|
}
|
|
|
|
|
2009-10-14 20:14:33 +00:00
|
|
|
TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const {
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this))
|
2013-08-06 01:03:05 +00:00
|
|
|
return Spec->getSpecializationKind();
|
|
|
|
|
2010-01-31 22:27:38 +00:00
|
|
|
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
|
2009-10-08 07:24:58 +00:00
|
|
|
return MSI->getTemplateSpecializationKind();
|
2013-09-27 20:14:12 +00:00
|
|
|
|
2009-10-08 07:24:58 +00:00
|
|
|
return TSK_Undeclared;
|
|
|
|
}
|
|
|
|
|
2019-05-03 23:51:38 +00:00
|
|
|
TemplateSpecializationKind
|
|
|
|
VarDecl::getTemplateSpecializationKindForInstantiation() const {
|
|
|
|
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
|
|
|
|
return MSI->getTemplateSpecializationKind();
|
|
|
|
|
|
|
|
if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this))
|
|
|
|
return Spec->getSpecializationKind();
|
|
|
|
|
|
|
|
return TSK_Undeclared;
|
|
|
|
}
|
|
|
|
|
2013-09-27 20:14:12 +00:00
|
|
|
SourceLocation VarDecl::getPointOfInstantiation() const {
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this))
|
2013-09-27 20:14:12 +00:00
|
|
|
return Spec->getPointOfInstantiation();
|
|
|
|
|
|
|
|
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
|
|
|
|
return MSI->getPointOfInstantiation();
|
|
|
|
|
|
|
|
return SourceLocation();
|
|
|
|
}
|
|
|
|
|
2013-08-06 01:03:05 +00:00
|
|
|
VarTemplateDecl *VarDecl::getDescribedVarTemplate() const {
|
|
|
|
return getASTContext().getTemplateOrSpecializationInfo(this)
|
|
|
|
.dyn_cast<VarTemplateDecl *>();
|
|
|
|
}
|
|
|
|
|
|
|
|
void VarDecl::setDescribedVarTemplate(VarTemplateDecl *Template) {
|
|
|
|
getASTContext().setTemplateOrSpecializationInfo(this, Template);
|
|
|
|
}
|
|
|
|
|
2018-05-17 16:15:07 +00:00
|
|
|
bool VarDecl::isKnownToBeDefined() const {
|
|
|
|
const auto &LangOpts = getASTContext().getLangOpts();
|
|
|
|
// In CUDA mode without relocatable device code, variables of form 'extern
|
|
|
|
// __shared__ Foo foo[]' are pointers to the base of the GPU core's shared
|
|
|
|
// memory pool. These are never undefined variables, even if they appear
|
|
|
|
// inside of an anon namespace or static function.
|
|
|
|
//
|
|
|
|
// With CUDA relocatable device code enabled, these variables don't get
|
|
|
|
// special handling; they're treated like regular extern variables.
|
2018-10-02 17:48:54 +00:00
|
|
|
if (LangOpts.CUDA && !LangOpts.GPURelocatableDeviceCode &&
|
2018-05-17 16:15:07 +00:00
|
|
|
hasExternalStorage() && hasAttr<CUDASharedAttr>() &&
|
|
|
|
isa<IncompleteArrayType>(getType()))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return hasDefinition();
|
|
|
|
}
|
|
|
|
|
2018-08-21 17:24:06 +00:00
|
|
|
bool VarDecl::isNoDestroy(const ASTContext &Ctx) const {
|
|
|
|
return hasGlobalStorage() && (hasAttr<NoDestroyAttr>() ||
|
|
|
|
(!Ctx.getLangOpts().RegisterStaticDestructors &&
|
|
|
|
!hasAttr<AlwaysDestroyAttr>()));
|
|
|
|
}
|
|
|
|
|
2019-09-29 05:08:46 +00:00
|
|
|
QualType::DestructionKind
|
|
|
|
VarDecl::needsDestruction(const ASTContext &Ctx) const {
|
2020-10-26 19:08:57 +00:00
|
|
|
if (EvaluatedStmt *Eval = getEvaluatedStmt())
|
2019-09-29 05:08:46 +00:00
|
|
|
if (Eval->HasConstantDestruction)
|
|
|
|
return QualType::DK_none;
|
|
|
|
|
|
|
|
if (isNoDestroy(Ctx))
|
|
|
|
return QualType::DK_none;
|
|
|
|
|
|
|
|
return getType().isDestructedType();
|
|
|
|
}
|
|
|
|
|
2022-04-14 22:20:37 +00:00
|
|
|
bool VarDecl::hasFlexibleArrayInit(const ASTContext &Ctx) const {
|
|
|
|
assert(hasInit() && "Expect initializer to check for flexible array init");
|
|
|
|
auto *Ty = getType()->getAs<RecordType>();
|
|
|
|
if (!Ty || !Ty->getDecl()->hasFlexibleArrayMember())
|
|
|
|
return false;
|
|
|
|
auto *List = dyn_cast<InitListExpr>(getInit()->IgnoreParens());
|
|
|
|
if (!List)
|
|
|
|
return false;
|
|
|
|
const Expr *FlexibleInit = List->getInit(List->getNumInits() - 1);
|
|
|
|
auto InitTy = Ctx.getAsConstantArrayType(FlexibleInit->getType());
|
|
|
|
if (!InitTy)
|
|
|
|
return false;
|
|
|
|
return InitTy->getSize() != 0;
|
|
|
|
}
|
|
|
|
|
2022-04-14 18:56:40 +00:00
|
|
|
CharUnits VarDecl::getFlexibleArrayInitChars(const ASTContext &Ctx) const {
|
|
|
|
assert(hasInit() && "Expect initializer to check for flexible array init");
|
|
|
|
auto *Ty = getType()->getAs<RecordType>();
|
|
|
|
if (!Ty || !Ty->getDecl()->hasFlexibleArrayMember())
|
|
|
|
return CharUnits::Zero();
|
|
|
|
auto *List = dyn_cast<InitListExpr>(getInit()->IgnoreParens());
|
|
|
|
if (!List)
|
|
|
|
return CharUnits::Zero();
|
2022-04-14 22:20:37 +00:00
|
|
|
const Expr *FlexibleInit = List->getInit(List->getNumInits() - 1);
|
2022-04-14 18:56:40 +00:00
|
|
|
auto InitTy = Ctx.getAsConstantArrayType(FlexibleInit->getType());
|
|
|
|
if (!InitTy)
|
|
|
|
return CharUnits::Zero();
|
2022-04-14 22:20:37 +00:00
|
|
|
CharUnits FlexibleArraySize = Ctx.getTypeSizeInChars(InitTy);
|
|
|
|
const ASTRecordLayout &RL = Ctx.getASTRecordLayout(Ty->getDecl());
|
|
|
|
CharUnits FlexibleArrayOffset =
|
|
|
|
Ctx.toCharUnitsFromBits(RL.getFieldOffset(RL.getFieldCount() - 1));
|
|
|
|
if (FlexibleArrayOffset + FlexibleArraySize < RL.getSize())
|
|
|
|
return CharUnits::Zero();
|
|
|
|
return FlexibleArrayOffset + FlexibleArraySize - RL.getSize();
|
2022-04-14 18:56:40 +00:00
|
|
|
}
|
|
|
|
|
2009-10-14 21:29:40 +00:00
|
|
|
MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const {
|
2013-08-01 04:12:04 +00:00
|
|
|
if (isStaticDataMember())
|
2013-08-06 01:03:05 +00:00
|
|
|
// FIXME: Remove ?
|
|
|
|
// return getASTContext().getInstantiatedFromStaticDataMember(this);
|
|
|
|
return getASTContext().getTemplateOrSpecializationInfo(this)
|
|
|
|
.dyn_cast<MemberSpecializationInfo *>();
|
2014-05-12 05:36:57 +00:00
|
|
|
return nullptr;
|
2009-10-12 20:18:28 +00:00
|
|
|
}
|
|
|
|
|
2009-10-15 17:21:20 +00:00
|
|
|
void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
|
|
|
|
SourceLocation PointOfInstantiation) {
|
2013-09-27 20:14:12 +00:00
|
|
|
assert((isa<VarTemplateSpecializationDecl>(this) ||
|
|
|
|
getMemberSpecializationInfo()) &&
|
|
|
|
"not a variable or static data member template specialization");
|
|
|
|
|
2013-08-06 01:03:05 +00:00
|
|
|
if (VarTemplateSpecializationDecl *Spec =
|
|
|
|
dyn_cast<VarTemplateSpecializationDecl>(this)) {
|
|
|
|
Spec->setSpecializationKind(TSK);
|
2019-05-03 23:51:38 +00:00
|
|
|
if (TSK != TSK_ExplicitSpecialization &&
|
|
|
|
PointOfInstantiation.isValid() &&
|
2017-12-05 01:31:47 +00:00
|
|
|
Spec->getPointOfInstantiation().isInvalid()) {
|
2013-08-06 01:03:05 +00:00
|
|
|
Spec->setPointOfInstantiation(PointOfInstantiation);
|
2017-12-05 01:31:47 +00:00
|
|
|
if (ASTMutationListener *L = getASTContext().getASTMutationListener())
|
|
|
|
L->InstantiationRequested(this);
|
|
|
|
}
|
2019-05-03 23:51:38 +00:00
|
|
|
} else if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) {
|
2013-08-06 01:03:05 +00:00
|
|
|
MSI->setTemplateSpecializationKind(TSK);
|
|
|
|
if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() &&
|
2017-12-05 01:31:47 +00:00
|
|
|
MSI->getPointOfInstantiation().isInvalid()) {
|
2013-08-06 01:03:05 +00:00
|
|
|
MSI->setPointOfInstantiation(PointOfInstantiation);
|
2017-12-05 01:31:47 +00:00
|
|
|
if (ASTMutationListener *L = getASTContext().getASTMutationListener())
|
|
|
|
L->InstantiationRequested(this);
|
|
|
|
}
|
2013-08-06 01:03:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
VarDecl::setInstantiationOfStaticDataMember(VarDecl *VD,
|
|
|
|
TemplateSpecializationKind TSK) {
|
|
|
|
assert(getASTContext().getTemplateOrSpecializationInfo(this).isNull() &&
|
|
|
|
"Previous template or instantiation?");
|
|
|
|
getASTContext().setInstantiatedFromStaticDataMember(this, VD, TSK);
|
2009-07-24 20:34:43 +00:00
|
|
|
}
|
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ParmVarDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-03-10 23:43:53 +00:00
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
|
2011-03-08 08:55:46 +00:00
|
|
|
SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc, IdentifierInfo *Id,
|
2010-01-26 22:01:41 +00:00
|
|
|
QualType T, TypeSourceInfo *TInfo,
|
2013-04-03 19:27:57 +00:00
|
|
|
StorageClass S, Expr *DefArg) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-16 23:01:30 +00:00
|
|
|
return new (C, DC) ParmVarDecl(ParmVar, C, DC, StartLoc, IdLoc, Id, T, TInfo,
|
2013-11-22 09:01:48 +00:00
|
|
|
S, DefArg);
|
2009-03-10 23:43:53 +00:00
|
|
|
}
|
|
|
|
|
2013-06-24 17:51:48 +00:00
|
|
|
QualType ParmVarDecl::getOriginalType() const {
|
|
|
|
TypeSourceInfo *TSI = getTypeSourceInfo();
|
|
|
|
QualType T = TSI ? TSI->getType() : getType();
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *DT = dyn_cast<DecayedType>(T))
|
2013-06-24 17:51:48 +00:00
|
|
|
return DT->getOriginalType();
|
|
|
|
return T;
|
|
|
|
}
|
|
|
|
|
2012-01-05 21:55:30 +00:00
|
|
|
ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-16 23:01:30 +00:00
|
|
|
return new (C, ID)
|
|
|
|
ParmVarDecl(ParmVar, C, nullptr, SourceLocation(), SourceLocation(),
|
2021-01-04 22:17:45 +00:00
|
|
|
nullptr, QualType(), nullptr, SC_None, nullptr);
|
2012-01-05 21:55:30 +00:00
|
|
|
}
|
|
|
|
|
2011-07-30 17:23:26 +00:00
|
|
|
SourceRange ParmVarDecl::getSourceRange() const {
|
|
|
|
if (!hasInheritedDefaultArg()) {
|
|
|
|
SourceRange ArgRange = getDefaultArgRange();
|
|
|
|
if (ArgRange.isValid())
|
|
|
|
return SourceRange(getOuterLocStart(), ArgRange.getEnd());
|
|
|
|
}
|
|
|
|
|
2013-04-17 01:56:48 +00:00
|
|
|
// DeclaratorDecl considers the range of postfix types as overlapping with the
|
|
|
|
// declaration name, but this is not the case with parameters in ObjC methods.
|
|
|
|
if (isa<ObjCMethodDecl>(getDeclContext()))
|
2018-08-09 21:08:08 +00:00
|
|
|
return SourceRange(DeclaratorDecl::getBeginLoc(), getLocation());
|
2013-04-17 01:56:48 +00:00
|
|
|
|
2011-07-30 17:23:26 +00:00
|
|
|
return DeclaratorDecl::getSourceRange();
|
|
|
|
}
|
|
|
|
|
2020-12-28 19:52:27 +00:00
|
|
|
bool ParmVarDecl::isDestroyedInCallee() const {
|
2021-10-08 09:20:45 +00:00
|
|
|
// ns_consumed only affects code generation in ARC
|
2020-12-28 19:52:27 +00:00
|
|
|
if (hasAttr<NSConsumedAttr>())
|
2021-10-08 09:20:45 +00:00
|
|
|
return getASTContext().getLangOpts().ObjCAutoRefCount;
|
2020-12-28 19:52:27 +00:00
|
|
|
|
2021-10-08 09:20:45 +00:00
|
|
|
// FIXME: isParamDestroyedInCallee() should probably imply
|
|
|
|
// isDestructedType()
|
2020-12-28 19:52:27 +00:00
|
|
|
auto *RT = getType()->getAs<RecordType>();
|
2021-10-08 09:20:45 +00:00
|
|
|
if (RT && RT->getDecl()->isParamDestroyedInCallee() &&
|
|
|
|
getType().isDestructedType())
|
2020-12-28 19:52:27 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
Expr *ParmVarDecl::getDefaultArg() {
|
|
|
|
assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!");
|
|
|
|
assert(!hasUninstantiatedDefaultArg() &&
|
|
|
|
"Default argument is not yet instantiated!");
|
2015-11-09 17:53:06 +00:00
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
Expr *Arg = getInit();
|
2023-09-13 12:53:27 +00:00
|
|
|
if (auto *E = dyn_cast_if_present<FullExpr>(Arg))
|
2022-10-23 15:32:58 +00:00
|
|
|
return E->getSubExpr();
|
2010-01-26 22:01:41 +00:00
|
|
|
|
|
|
|
return Arg;
|
|
|
|
}
|
|
|
|
|
2015-12-30 02:51:00 +00:00
|
|
|
void ParmVarDecl::setDefaultArg(Expr *defarg) {
|
|
|
|
ParmVarDeclBits.DefaultArgKind = DAK_Normal;
|
|
|
|
Init = defarg;
|
|
|
|
}
|
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
SourceRange ParmVarDecl::getDefaultArgRange() const {
|
2015-12-30 02:51:00 +00:00
|
|
|
switch (ParmVarDeclBits.DefaultArgKind) {
|
|
|
|
case DAK_None:
|
|
|
|
case DAK_Unparsed:
|
|
|
|
// Nothing we can do here.
|
|
|
|
return SourceRange();
|
2010-01-26 22:01:41 +00:00
|
|
|
|
2015-12-30 02:51:00 +00:00
|
|
|
case DAK_Uninstantiated:
|
2010-01-26 22:01:41 +00:00
|
|
|
return getUninstantiatedDefaultArg()->getSourceRange();
|
|
|
|
|
2015-12-30 02:51:00 +00:00
|
|
|
case DAK_Normal:
|
|
|
|
if (const Expr *E = getInit())
|
|
|
|
return E->getSourceRange();
|
|
|
|
|
|
|
|
// Missing an actual expression, may be invalid.
|
|
|
|
return SourceRange();
|
|
|
|
}
|
|
|
|
llvm_unreachable("Invalid default argument kind.");
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParmVarDecl::setUninstantiatedDefaultArg(Expr *arg) {
|
|
|
|
ParmVarDeclBits.DefaultArgKind = DAK_Uninstantiated;
|
|
|
|
Init = arg;
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr *ParmVarDecl::getUninstantiatedDefaultArg() {
|
|
|
|
assert(hasUninstantiatedDefaultArg() &&
|
|
|
|
"Wrong kind of initialization expression!");
|
2023-09-13 12:53:27 +00:00
|
|
|
return cast_if_present<Expr>(Init.get<Stmt *>());
|
2015-12-30 02:51:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ParmVarDecl::hasDefaultArg() const {
|
|
|
|
// FIXME: We should just return false for DAK_None here once callers are
|
|
|
|
// prepared for the case that we encountered an invalid default argument and
|
|
|
|
// were unable to even build an invalid expression.
|
|
|
|
return hasUnparsedDefaultArg() || hasUninstantiatedDefaultArg() ||
|
|
|
|
!Init.isNull();
|
2009-07-05 22:21:56 +00:00
|
|
|
}
|
|
|
|
|
2011-10-06 05:00:56 +00:00
|
|
|
void ParmVarDecl::setParameterIndexLarge(unsigned parameterIndex) {
|
|
|
|
getASTContext().setParameterIndex(this, parameterIndex);
|
|
|
|
ParmVarDeclBits.ParameterIndex = ParameterIndexSentinel;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned ParmVarDecl::getParameterIndexLarge() const {
|
|
|
|
return getASTContext().getParameterIndex(this);
|
|
|
|
}
|
|
|
|
|
2008-11-09 23:41:00 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
2008-03-31 00:36:02 +00:00
|
|
|
// FunctionDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-08-01 21:02:40 +00:00
|
|
|
FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation StartLoc,
|
|
|
|
const DeclarationNameInfo &NameInfo, QualType T,
|
|
|
|
TypeSourceInfo *TInfo, StorageClass S,
|
2021-07-29 16:02:20 +00:00
|
|
|
bool UsesFPIntrin, bool isInlineSpecified,
|
2020-01-09 13:07:51 +00:00
|
|
|
ConstexprSpecKind ConstexprKind,
|
|
|
|
Expr *TrailingRequiresClause)
|
2018-08-01 21:02:40 +00:00
|
|
|
: DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
|
|
|
|
StartLoc),
|
2019-12-05 21:37:35 +00:00
|
|
|
DeclContext(DK), redeclarable_base(C), Body(), ODRHash(0),
|
2018-08-01 21:02:40 +00:00
|
|
|
EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) {
|
2018-11-11 00:56:15 +00:00
|
|
|
assert(T.isNull() || T->isFunctionType());
|
2021-01-04 22:17:45 +00:00
|
|
|
FunctionDeclBits.SClass = S;
|
2018-12-03 13:04:10 +00:00
|
|
|
FunctionDeclBits.IsInline = isInlineSpecified;
|
|
|
|
FunctionDeclBits.IsInlineSpecified = isInlineSpecified;
|
|
|
|
FunctionDeclBits.IsVirtualAsWritten = false;
|
|
|
|
FunctionDeclBits.IsPure = false;
|
|
|
|
FunctionDeclBits.HasInheritedPrototype = false;
|
|
|
|
FunctionDeclBits.HasWrittenPrototype = true;
|
|
|
|
FunctionDeclBits.IsDeleted = false;
|
|
|
|
FunctionDeclBits.IsTrivial = false;
|
|
|
|
FunctionDeclBits.IsTrivialForCall = false;
|
|
|
|
FunctionDeclBits.IsDefaulted = false;
|
|
|
|
FunctionDeclBits.IsExplicitlyDefaulted = false;
|
2019-12-05 21:37:35 +00:00
|
|
|
FunctionDeclBits.HasDefaultedFunctionInfo = false;
|
2022-06-16 17:52:12 +00:00
|
|
|
FunctionDeclBits.IsIneligibleOrNotSelected = false;
|
2018-12-03 13:04:10 +00:00
|
|
|
FunctionDeclBits.HasImplicitReturnZero = false;
|
|
|
|
FunctionDeclBits.IsLateTemplateParsed = false;
|
2020-11-16 19:08:33 +00:00
|
|
|
FunctionDeclBits.ConstexprKind = static_cast<uint64_t>(ConstexprKind);
|
2023-05-08 10:18:43 +00:00
|
|
|
FunctionDeclBits.BodyContainsImmediateEscalatingExpression = false;
|
2018-12-03 13:04:10 +00:00
|
|
|
FunctionDeclBits.InstantiationIsPending = false;
|
|
|
|
FunctionDeclBits.UsesSEHTry = false;
|
2021-07-29 16:02:20 +00:00
|
|
|
FunctionDeclBits.UsesFPIntrin = UsesFPIntrin;
|
2018-12-03 13:04:10 +00:00
|
|
|
FunctionDeclBits.HasSkippedBody = false;
|
|
|
|
FunctionDeclBits.WillHaveBody = false;
|
|
|
|
FunctionDeclBits.IsMultiVersion = false;
|
2022-12-01 02:44:10 +00:00
|
|
|
FunctionDeclBits.DeductionCandidateKind =
|
|
|
|
static_cast<unsigned char>(DeductionCandidate::Normal);
|
2018-12-03 13:04:10 +00:00
|
|
|
FunctionDeclBits.HasODRHash = false;
|
2022-08-19 20:57:45 +00:00
|
|
|
FunctionDeclBits.FriendConstraintRefersToEnclosingTemplate = false;
|
2020-01-09 13:07:51 +00:00
|
|
|
if (TrailingRequiresClause)
|
|
|
|
setTrailingRequiresClause(TrailingRequiresClause);
|
2018-08-01 21:02:40 +00:00
|
|
|
}
|
|
|
|
|
2013-02-22 15:46:01 +00:00
|
|
|
void FunctionDecl::getNameForDiagnostic(
|
|
|
|
raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
|
|
|
|
NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
|
2011-02-19 18:51:44 +00:00
|
|
|
const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs();
|
|
|
|
if (TemplateArgs)
|
2017-11-28 16:14:14 +00:00
|
|
|
printTemplateArgumentList(OS, TemplateArgs->asArray(), Policy);
|
2011-02-19 18:51:44 +00:00
|
|
|
}
|
|
|
|
|
2010-04-29 16:49:01 +00:00
|
|
|
bool FunctionDecl::isVariadic() const {
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *FT = getType()->getAs<FunctionProtoType>())
|
2010-04-29 16:49:01 +00:00
|
|
|
return FT->isVariadic();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-12-05 21:37:35 +00:00
|
|
|
FunctionDecl::DefaultedFunctionInfo *
|
|
|
|
FunctionDecl::DefaultedFunctionInfo::Create(ASTContext &Context,
|
|
|
|
ArrayRef<DeclAccessPair> Lookups) {
|
|
|
|
DefaultedFunctionInfo *Info = new (Context.Allocate(
|
|
|
|
totalSizeToAlloc<DeclAccessPair>(Lookups.size()),
|
|
|
|
std::max(alignof(DefaultedFunctionInfo), alignof(DeclAccessPair))))
|
|
|
|
DefaultedFunctionInfo;
|
|
|
|
Info->NumLookups = Lookups.size();
|
|
|
|
std::uninitialized_copy(Lookups.begin(), Lookups.end(),
|
|
|
|
Info->getTrailingObjects<DeclAccessPair>());
|
|
|
|
return Info;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FunctionDecl::setDefaultedFunctionInfo(DefaultedFunctionInfo *Info) {
|
|
|
|
assert(!FunctionDeclBits.HasDefaultedFunctionInfo && "already have this");
|
|
|
|
assert(!Body && "can't replace function body with defaulted function info");
|
|
|
|
|
|
|
|
FunctionDeclBits.HasDefaultedFunctionInfo = true;
|
|
|
|
DefaultedInfo = Info;
|
|
|
|
}
|
|
|
|
|
|
|
|
FunctionDecl::DefaultedFunctionInfo *
|
|
|
|
FunctionDecl::getDefaultedFunctionInfo() const {
|
|
|
|
return FunctionDeclBits.HasDefaultedFunctionInfo ? DefaultedInfo : nullptr;
|
|
|
|
}
|
|
|
|
|
2010-07-07 11:31:19 +00:00
|
|
|
bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const {
|
2022-09-04 06:27:27 +00:00
|
|
|
for (auto *I : redecls()) {
|
2017-02-15 12:30:35 +00:00
|
|
|
if (I->doesThisDeclarationHaveABody()) {
|
2014-03-06 23:45:36 +00:00
|
|
|
Definition = I;
|
2010-07-07 11:31:19 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-12-05 21:37:35 +00:00
|
|
|
bool FunctionDecl::hasTrivialBody() const {
|
2011-05-14 23:26:09 +00:00
|
|
|
Stmt *S = getBody();
|
|
|
|
if (!S) {
|
|
|
|
// Since we don't have a body for this function, we don't know if it's
|
|
|
|
// trivial or not.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isa<CompoundStmt>(S) && cast<CompoundStmt>(S)->body_empty())
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-10-31 01:30:56 +00:00
|
|
|
bool FunctionDecl::isThisDeclarationInstantiatedFromAFriendDefinition() const {
|
|
|
|
if (!getFriendObjectKind())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Check for a friend function instantiated from a friend function
|
|
|
|
// definition in a templated class.
|
|
|
|
if (const FunctionDecl *InstantiatedFrom =
|
|
|
|
getInstantiatedFromMemberFunction())
|
|
|
|
return InstantiatedFrom->getFriendObjectKind() &&
|
|
|
|
InstantiatedFrom->isThisDeclarationADefinition();
|
|
|
|
|
|
|
|
// Check for a friend function template instantiated from a friend
|
|
|
|
// function template definition in a templated class.
|
|
|
|
if (const FunctionTemplateDecl *Template = getDescribedFunctionTemplate()) {
|
|
|
|
if (const FunctionTemplateDecl *InstantiatedFrom =
|
|
|
|
Template->getInstantiatedFromMemberTemplate())
|
|
|
|
return InstantiatedFrom->getFriendObjectKind() &&
|
|
|
|
InstantiatedFrom->isThisDeclarationADefinition();
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FunctionDecl::isDefined(const FunctionDecl *&Definition,
|
|
|
|
bool CheckForPendingFriendDefinition) const {
|
|
|
|
for (const FunctionDecl *FD : redecls()) {
|
|
|
|
if (FD->isThisDeclarationADefinition()) {
|
|
|
|
Definition = FD;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this is a friend function defined in a class template, it does not
|
|
|
|
// have a body until it is used, nevertheless it is a definition, see
|
|
|
|
// [temp.inst]p2:
|
|
|
|
//
|
|
|
|
// ... for the purpose of determining whether an instantiated redeclaration
|
|
|
|
// is valid according to [basic.def.odr] and [class.mem], a declaration that
|
|
|
|
// corresponds to a definition in the template is considered to be a
|
|
|
|
// definition.
|
|
|
|
//
|
|
|
|
// The following code must produce redefinition error:
|
|
|
|
//
|
|
|
|
// template<typename T> struct C20 { friend void func_20() {} };
|
|
|
|
// C20<int> c20i;
|
|
|
|
// void func_20() {}
|
|
|
|
//
|
|
|
|
if (CheckForPendingFriendDefinition &&
|
|
|
|
FD->isThisDeclarationInstantiatedFromAFriendDefinition()) {
|
|
|
|
Definition = FD;
|
2011-05-06 20:44:56 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-06-30 02:35:26 +00:00
|
|
|
Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
|
2013-10-19 01:37:17 +00:00
|
|
|
if (!hasBody(Definition))
|
2014-05-12 05:36:57 +00:00
|
|
|
return nullptr;
|
2013-10-19 01:37:17 +00:00
|
|
|
|
2019-12-05 21:37:35 +00:00
|
|
|
assert(!Definition->FunctionDeclBits.HasDefaultedFunctionInfo &&
|
|
|
|
"definition should not have a body");
|
2013-10-19 01:37:17 +00:00
|
|
|
if (Definition->Body)
|
|
|
|
return Definition->Body.get(getASTContext().getExternalSource());
|
2008-04-21 02:02:58 +00:00
|
|
|
|
2014-05-12 05:36:57 +00:00
|
|
|
return nullptr;
|
2007-01-21 07:42:07 +00:00
|
|
|
}
|
|
|
|
|
2009-06-20 08:09:14 +00:00
|
|
|
void FunctionDecl::setBody(Stmt *B) {
|
2019-12-05 21:37:35 +00:00
|
|
|
FunctionDeclBits.HasDefaultedFunctionInfo = false;
|
|
|
|
Body = LazyDeclStmtPtr(B);
|
2010-12-06 17:49:01 +00:00
|
|
|
if (B)
|
2018-08-09 21:09:38 +00:00
|
|
|
EndRangeLoc = B->getEndLoc();
|
2009-06-20 08:09:14 +00:00
|
|
|
}
|
|
|
|
|
2010-09-28 21:55:22 +00:00
|
|
|
void FunctionDecl::setPure(bool P) {
|
2018-08-01 21:02:40 +00:00
|
|
|
FunctionDeclBits.IsPure = P;
|
2010-09-28 21:55:22 +00:00
|
|
|
if (P)
|
2015-11-09 17:53:06 +00:00
|
|
|
if (auto *Parent = dyn_cast<CXXRecordDecl>(getDeclContext()))
|
2010-09-28 21:55:22 +00:00
|
|
|
Parent->markedVirtualFunctionPure();
|
|
|
|
}
|
|
|
|
|
2013-07-21 23:12:18 +00:00
|
|
|
template<std::size_t Len>
|
|
|
|
static bool isNamed(const NamedDecl *ND, const char (&Str)[Len]) {
|
|
|
|
IdentifierInfo *II = ND->getIdentifier();
|
|
|
|
return II && II->isStr(Str);
|
|
|
|
}
|
|
|
|
|
2023-05-08 10:18:43 +00:00
|
|
|
bool FunctionDecl::isImmediateEscalating() const {
|
|
|
|
// C++23 [expr.const]/p17
|
|
|
|
// An immediate-escalating function is
|
|
|
|
// - the call operator of a lambda that is not declared with the consteval
|
|
|
|
// specifier,
|
|
|
|
if (isLambdaCallOperator(this) && !isConsteval())
|
|
|
|
return true;
|
|
|
|
// - a defaulted special member function that is not declared with the
|
|
|
|
// consteval specifier,
|
|
|
|
if (isDefaulted() && !isConsteval())
|
|
|
|
return true;
|
|
|
|
// - a function that results from the instantiation of a templated entity
|
|
|
|
// defined with the constexpr specifier.
|
|
|
|
TemplatedKind TK = getTemplatedKind();
|
|
|
|
if (TK != TK_NonTemplate && TK != TK_DependentNonTemplate &&
|
|
|
|
isConstexprSpecified())
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FunctionDecl::isImmediateFunction() const {
|
|
|
|
// C++23 [expr.const]/p18
|
|
|
|
// An immediate function is a function or constructor that is
|
|
|
|
// - declared with the consteval specifier
|
|
|
|
if (isConsteval())
|
|
|
|
return true;
|
|
|
|
// - an immediate-escalating function F whose function body contains an
|
|
|
|
// immediate-escalating expression
|
|
|
|
if (isImmediateEscalating() && BodyContainsImmediateEscalatingExpressions())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (const auto *MD = dyn_cast<CXXMethodDecl>(this);
|
|
|
|
MD && MD->isLambdaStaticInvoker())
|
|
|
|
return MD->getParent()->getLambdaCallOperator()->isImmediateFunction();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-09-12 00:17:51 +00:00
|
|
|
bool FunctionDecl::isMain() const {
|
2011-05-15 17:49:20 +00:00
|
|
|
const TranslationUnitDecl *tunit =
|
|
|
|
dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext());
|
|
|
|
return tunit &&
|
2012-03-11 07:00:24 +00:00
|
|
|
!tunit->getASTContext().getLangOpts().Freestanding &&
|
2013-07-21 23:12:18 +00:00
|
|
|
isNamed(this, "main");
|
2011-05-15 17:49:20 +00:00
|
|
|
}
|
|
|
|
|
2013-09-16 22:44:20 +00:00
|
|
|
bool FunctionDecl::isMSVCRTEntryPoint() const {
|
|
|
|
const TranslationUnitDecl *TUnit =
|
|
|
|
dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext());
|
|
|
|
if (!TUnit)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Even though we aren't really targeting MSVCRT if we are freestanding,
|
|
|
|
// semantic analysis for these functions remains the same.
|
|
|
|
|
|
|
|
// MSVCRT entry points only exist on MSVCRT targets.
|
|
|
|
if (!TUnit->getASTContext().getTargetInfo().getTriple().isOSMSVCRT())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Nameless functions like constructors cannot be entry points.
|
|
|
|
if (!getIdentifier())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return llvm::StringSwitch<bool>(getName())
|
|
|
|
.Cases("main", // an ANSI console app
|
|
|
|
"wmain", // a Unicode console App
|
|
|
|
"WinMain", // an ANSI GUI app
|
|
|
|
"wWinMain", // a Unicode GUI app
|
|
|
|
"DllMain", // a DLL
|
|
|
|
true)
|
|
|
|
.Default(false);
|
|
|
|
}
|
|
|
|
|
2011-05-15 17:49:20 +00:00
|
|
|
bool FunctionDecl::isReservedGlobalPlacementOperator() const {
|
2023-01-04 10:57:33 +00:00
|
|
|
if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName)
|
|
|
|
return false;
|
|
|
|
if (getDeclName().getCXXOverloadedOperator() != OO_New &&
|
|
|
|
getDeclName().getCXXOverloadedOperator() != OO_Delete &&
|
|
|
|
getDeclName().getCXXOverloadedOperator() != OO_Array_New &&
|
|
|
|
getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
|
|
|
|
return false;
|
2011-05-15 17:49:20 +00:00
|
|
|
|
2014-01-19 23:25:37 +00:00
|
|
|
if (!getDeclContext()->getRedeclContext()->isTranslationUnit())
|
|
|
|
return false;
|
2011-05-15 17:49:20 +00:00
|
|
|
|
2015-11-09 17:53:06 +00:00
|
|
|
const auto *proto = getType()->castAs<FunctionProtoType>();
|
2014-01-20 20:26:09 +00:00
|
|
|
if (proto->getNumParams() != 2 || proto->isVariadic())
|
|
|
|
return false;
|
2011-05-15 17:49:20 +00:00
|
|
|
|
|
|
|
ASTContext &Context =
|
|
|
|
cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext())
|
|
|
|
->getASTContext();
|
|
|
|
|
|
|
|
// The result type and first argument type are constant across all
|
|
|
|
// these operators. The second argument must be exactly void*.
|
2014-01-20 20:26:09 +00:00
|
|
|
return (proto->getParamType(1).getCanonicalType() == Context.VoidPtrTy);
|
2009-02-24 01:23:02 +00:00
|
|
|
}
|
|
|
|
|
[clang] Annotating C++'s `operator new` with more attributes
Summary:
Right now we annotate C++'s `operator new` with `noalias` attribute,
which very much is healthy for optimizations.
However as per [[ http://eel.is/c++draft/basic.stc.dynamic.allocation | `[basic.stc.dynamic.allocation]` ]],
there are more promises on global `operator new`, namely:
* non-`std::nothrow_t` `operator new` *never* returns `nullptr`
* If `std::align_val_t align` parameter is taken, the pointer will also be `align`-aligned
* ~~global `operator new`-returned pointer is `__STDCPP_DEFAULT_NEW_ALIGNMENT__`-aligned ~~ It's more caveated than that.
Supplying this information may not cause immediate landslide effects
on any specific benchmarks, but it for sure will be healthy for optimizer
in the sense that the IR will better reflect the guarantees provided in the source code.
The caveat is `-fno-assume-sane-operator-new`, which currently prevents emitting `noalias`
attribute, and is automatically passed by Sanitizers ([[ https://bugs.llvm.org/show_bug.cgi?id=16386 | PR16386 ]]) - should it also cover these attributes?
The problem is that the flag is back-end-specific, as seen in `test/Modules/explicit-build-flags.cpp`.
But while it is okay to add `noalias` metadata in backend, we really should be adding at least
the alignment metadata to the AST, since that allows us to perform sema checks on it.
Reviewers: erichkeane, rjmccall, jdoerfert, eugenis, rsmith
Reviewed By: rsmith
Subscribers: xbolva00, jrtc27, atanasyan, nlopes, cfe-commits
Tags: #llvm, #clang
Differential Revision: https://reviews.llvm.org/D73380
2020-02-25 22:37:17 +00:00
|
|
|
bool FunctionDecl::isReplaceableGlobalAllocationFunction(
|
2023-01-14 20:31:01 +00:00
|
|
|
std::optional<unsigned> *AlignmentParam, bool *IsNothrow) const {
|
2013-07-21 23:12:18 +00:00
|
|
|
if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName)
|
|
|
|
return false;
|
|
|
|
if (getDeclName().getCXXOverloadedOperator() != OO_New &&
|
|
|
|
getDeclName().getCXXOverloadedOperator() != OO_Delete &&
|
|
|
|
getDeclName().getCXXOverloadedOperator() != OO_Array_New &&
|
|
|
|
getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (isa<CXXRecordDecl>(getDeclContext()))
|
|
|
|
return false;
|
2014-01-19 23:25:37 +00:00
|
|
|
|
|
|
|
// This can only fail for an invalid 'operator new' declaration.
|
|
|
|
if (!getDeclContext()->getRedeclContext()->isTranslationUnit())
|
|
|
|
return false;
|
2013-07-21 23:12:18 +00:00
|
|
|
|
2015-11-09 17:53:06 +00:00
|
|
|
const auto *FPT = getType()->castAs<FunctionProtoType>();
|
2023-05-01 18:04:59 +00:00
|
|
|
if (FPT->getNumParams() == 0 || FPT->getNumParams() > 4 || FPT->isVariadic())
|
2013-07-21 23:12:18 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// If this is a single-parameter function, it must be a replaceable global
|
|
|
|
// allocation or deallocation function.
|
2014-01-20 20:26:09 +00:00
|
|
|
if (FPT->getNumParams() == 1)
|
2013-07-21 23:12:18 +00:00
|
|
|
return true;
|
|
|
|
|
2016-10-10 18:54:32 +00:00
|
|
|
unsigned Params = 1;
|
|
|
|
QualType Ty = FPT->getParamType(Params);
|
2013-09-29 04:40:38 +00:00
|
|
|
ASTContext &Ctx = getASTContext();
|
2016-10-10 18:54:32 +00:00
|
|
|
|
|
|
|
auto Consume = [&] {
|
|
|
|
++Params;
|
|
|
|
Ty = Params < FPT->getNumParams() ? FPT->getParamType(Params) : QualType();
|
|
|
|
};
|
|
|
|
|
|
|
|
// In C++14, the next parameter can be a 'std::size_t' for sized delete.
|
|
|
|
bool IsSizedDelete = false;
|
2013-11-05 09:12:18 +00:00
|
|
|
if (Ctx.getLangOpts().SizedDeallocation &&
|
2016-10-10 18:54:32 +00:00
|
|
|
(getDeclName().getCXXOverloadedOperator() == OO_Delete ||
|
|
|
|
getDeclName().getCXXOverloadedOperator() == OO_Array_Delete) &&
|
|
|
|
Ctx.hasSameType(Ty, Ctx.getSizeType())) {
|
|
|
|
IsSizedDelete = true;
|
|
|
|
Consume();
|
|
|
|
}
|
|
|
|
|
|
|
|
// In C++17, the next parameter can be a 'std::align_val_t' for aligned
|
|
|
|
// new/delete.
|
2017-06-29 18:48:40 +00:00
|
|
|
if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT()) {
|
2016-10-10 18:54:32 +00:00
|
|
|
Consume();
|
[clang] Annotating C++'s `operator new` with more attributes
Summary:
Right now we annotate C++'s `operator new` with `noalias` attribute,
which very much is healthy for optimizations.
However as per [[ http://eel.is/c++draft/basic.stc.dynamic.allocation | `[basic.stc.dynamic.allocation]` ]],
there are more promises on global `operator new`, namely:
* non-`std::nothrow_t` `operator new` *never* returns `nullptr`
* If `std::align_val_t align` parameter is taken, the pointer will also be `align`-aligned
* ~~global `operator new`-returned pointer is `__STDCPP_DEFAULT_NEW_ALIGNMENT__`-aligned ~~ It's more caveated than that.
Supplying this information may not cause immediate landslide effects
on any specific benchmarks, but it for sure will be healthy for optimizer
in the sense that the IR will better reflect the guarantees provided in the source code.
The caveat is `-fno-assume-sane-operator-new`, which currently prevents emitting `noalias`
attribute, and is automatically passed by Sanitizers ([[ https://bugs.llvm.org/show_bug.cgi?id=16386 | PR16386 ]]) - should it also cover these attributes?
The problem is that the flag is back-end-specific, as seen in `test/Modules/explicit-build-flags.cpp`.
But while it is okay to add `noalias` metadata in backend, we really should be adding at least
the alignment metadata to the AST, since that allows us to perform sema checks on it.
Reviewers: erichkeane, rjmccall, jdoerfert, eugenis, rsmith
Reviewed By: rsmith
Subscribers: xbolva00, jrtc27, atanasyan, nlopes, cfe-commits
Tags: #llvm, #clang
Differential Revision: https://reviews.llvm.org/D73380
2020-02-25 22:37:17 +00:00
|
|
|
if (AlignmentParam)
|
|
|
|
*AlignmentParam = Params;
|
2017-06-29 18:48:40 +00:00
|
|
|
}
|
2016-10-10 18:54:32 +00:00
|
|
|
|
2023-05-01 18:04:59 +00:00
|
|
|
// If this is not a sized delete, the next parameter can be a
|
|
|
|
// 'const std::nothrow_t&'.
|
2016-10-10 18:54:32 +00:00
|
|
|
if (!IsSizedDelete && !Ty.isNull() && Ty->isReferenceType()) {
|
|
|
|
Ty = Ty->getPointeeType();
|
|
|
|
if (Ty.getCVRQualifiers() != Qualifiers::Const)
|
|
|
|
return false;
|
[clang] Annotating C++'s `operator new` with more attributes
Summary:
Right now we annotate C++'s `operator new` with `noalias` attribute,
which very much is healthy for optimizations.
However as per [[ http://eel.is/c++draft/basic.stc.dynamic.allocation | `[basic.stc.dynamic.allocation]` ]],
there are more promises on global `operator new`, namely:
* non-`std::nothrow_t` `operator new` *never* returns `nullptr`
* If `std::align_val_t align` parameter is taken, the pointer will also be `align`-aligned
* ~~global `operator new`-returned pointer is `__STDCPP_DEFAULT_NEW_ALIGNMENT__`-aligned ~~ It's more caveated than that.
Supplying this information may not cause immediate landslide effects
on any specific benchmarks, but it for sure will be healthy for optimizer
in the sense that the IR will better reflect the guarantees provided in the source code.
The caveat is `-fno-assume-sane-operator-new`, which currently prevents emitting `noalias`
attribute, and is automatically passed by Sanitizers ([[ https://bugs.llvm.org/show_bug.cgi?id=16386 | PR16386 ]]) - should it also cover these attributes?
The problem is that the flag is back-end-specific, as seen in `test/Modules/explicit-build-flags.cpp`.
But while it is okay to add `noalias` metadata in backend, we really should be adding at least
the alignment metadata to the AST, since that allows us to perform sema checks on it.
Reviewers: erichkeane, rjmccall, jdoerfert, eugenis, rsmith
Reviewed By: rsmith
Subscribers: xbolva00, jrtc27, atanasyan, nlopes, cfe-commits
Tags: #llvm, #clang
Differential Revision: https://reviews.llvm.org/D73380
2020-02-25 22:37:17 +00:00
|
|
|
if (Ty->isNothrowT()) {
|
|
|
|
if (IsNothrow)
|
|
|
|
*IsNothrow = true;
|
2016-10-10 18:54:32 +00:00
|
|
|
Consume();
|
[clang] Annotating C++'s `operator new` with more attributes
Summary:
Right now we annotate C++'s `operator new` with `noalias` attribute,
which very much is healthy for optimizations.
However as per [[ http://eel.is/c++draft/basic.stc.dynamic.allocation | `[basic.stc.dynamic.allocation]` ]],
there are more promises on global `operator new`, namely:
* non-`std::nothrow_t` `operator new` *never* returns `nullptr`
* If `std::align_val_t align` parameter is taken, the pointer will also be `align`-aligned
* ~~global `operator new`-returned pointer is `__STDCPP_DEFAULT_NEW_ALIGNMENT__`-aligned ~~ It's more caveated than that.
Supplying this information may not cause immediate landslide effects
on any specific benchmarks, but it for sure will be healthy for optimizer
in the sense that the IR will better reflect the guarantees provided in the source code.
The caveat is `-fno-assume-sane-operator-new`, which currently prevents emitting `noalias`
attribute, and is automatically passed by Sanitizers ([[ https://bugs.llvm.org/show_bug.cgi?id=16386 | PR16386 ]]) - should it also cover these attributes?
The problem is that the flag is back-end-specific, as seen in `test/Modules/explicit-build-flags.cpp`.
But while it is okay to add `noalias` metadata in backend, we really should be adding at least
the alignment metadata to the AST, since that allows us to perform sema checks on it.
Reviewers: erichkeane, rjmccall, jdoerfert, eugenis, rsmith
Reviewed By: rsmith
Subscribers: xbolva00, jrtc27, atanasyan, nlopes, cfe-commits
Tags: #llvm, #clang
Differential Revision: https://reviews.llvm.org/D73380
2020-02-25 22:37:17 +00:00
|
|
|
}
|
2016-10-10 18:54:32 +00:00
|
|
|
}
|
|
|
|
|
2023-05-01 18:04:59 +00:00
|
|
|
// Finally, recognize the not yet standard versions of new that take a
|
|
|
|
// hot/cold allocation hint (__hot_cold_t). These are currently supported by
|
|
|
|
// tcmalloc (see
|
|
|
|
// https://github.com/google/tcmalloc/blob/220043886d4e2efff7a5702d5172cb8065253664/tcmalloc/malloc_extension.h#L53).
|
|
|
|
if (!IsSizedDelete && !Ty.isNull() && Ty->isEnumeralType()) {
|
|
|
|
QualType T = Ty;
|
|
|
|
while (const auto *TD = T->getAs<TypedefType>())
|
|
|
|
T = TD->getDecl()->getUnderlyingType();
|
2023-05-20 02:41:27 +00:00
|
|
|
IdentifierInfo *II = T->castAs<EnumType>()->getDecl()->getIdentifier();
|
2023-05-01 18:04:59 +00:00
|
|
|
if (II && II->isStr("__hot_cold_t"))
|
|
|
|
Consume();
|
|
|
|
}
|
|
|
|
|
2016-10-10 18:54:32 +00:00
|
|
|
return Params == FPT->getNumParams();
|
2013-07-21 23:12:18 +00:00
|
|
|
}
|
|
|
|
|
2020-01-16 18:54:38 +00:00
|
|
|
bool FunctionDecl::isInlineBuiltinDeclaration() const {
|
|
|
|
if (!getBuiltinID())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const FunctionDecl *Definition;
|
2023-04-19 14:15:17 +00:00
|
|
|
if (!hasBody(Definition))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!Definition->isInlineSpecified() ||
|
|
|
|
!Definition->hasAttr<AlwaysInlineAttr>())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ASTContext &Context = getASTContext();
|
2023-05-31 05:57:35 +00:00
|
|
|
switch (Context.GetGVALinkageForFunction(Definition)) {
|
2023-04-19 14:15:17 +00:00
|
|
|
case GVA_Internal:
|
|
|
|
case GVA_DiscardableODR:
|
|
|
|
case GVA_StrongODR:
|
|
|
|
return false;
|
|
|
|
case GVA_AvailableExternally:
|
|
|
|
case GVA_StrongExternal:
|
|
|
|
return true;
|
|
|
|
}
|
2023-05-30 09:29:47 +00:00
|
|
|
llvm_unreachable("Unknown GVALinkage");
|
2020-01-16 18:54:38 +00:00
|
|
|
}
|
|
|
|
|
2017-10-13 01:55:36 +00:00
|
|
|
bool FunctionDecl::isDestroyingOperatorDelete() const {
|
|
|
|
// C++ P0722:
|
|
|
|
// Within a class C, a single object deallocation function with signature
|
|
|
|
// (T, std::destroying_delete_t, <more params>)
|
|
|
|
// is a destroying operator delete.
|
|
|
|
if (!isa<CXXMethodDecl>(this) || getOverloadedOperator() != OO_Delete ||
|
|
|
|
getNumParams() < 2)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
auto *RD = getParamDecl(1)->getType()->getAsCXXRecordDecl();
|
|
|
|
return RD && RD->isInStdNamespace() && RD->getIdentifier() &&
|
|
|
|
RD->getIdentifier()->isStr("destroying_delete_t");
|
|
|
|
}
|
|
|
|
|
2013-02-14 01:18:37 +00:00
|
|
|
LanguageLinkage FunctionDecl::getLanguageLinkage() const {
|
2014-05-31 06:11:02 +00:00
|
|
|
return getDeclLanguageLinkage(*this);
|
2012-12-28 14:21:58 +00:00
|
|
|
}
|
|
|
|
|
2013-03-14 03:07:35 +00:00
|
|
|
bool FunctionDecl::isExternC() const {
|
2014-05-31 06:11:02 +00:00
|
|
|
return isDeclExternC(*this);
|
2013-05-05 20:15:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool FunctionDecl::isInExternCContext() const {
|
2019-05-07 14:22:34 +00:00
|
|
|
if (hasAttr<OpenCLKernelAttr>())
|
|
|
|
return true;
|
2013-11-14 02:13:03 +00:00
|
|
|
return getLexicalDeclContext()->isExternCContext();
|
2013-05-05 20:15:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool FunctionDecl::isInExternCXXContext() const {
|
2013-11-14 02:13:03 +00:00
|
|
|
return getLexicalDeclContext()->isExternCXXContext();
|
2013-03-14 03:07:35 +00:00
|
|
|
}
|
|
|
|
|
2009-03-31 16:35:03 +00:00
|
|
|
bool FunctionDecl::isGlobal() const {
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *Method = dyn_cast<CXXMethodDecl>(this))
|
2009-03-31 16:35:03 +00:00
|
|
|
return Method->isStatic();
|
|
|
|
|
2021-01-04 22:17:45 +00:00
|
|
|
if (getCanonicalDecl()->getStorageClass() == SC_Static)
|
2009-03-31 16:35:03 +00:00
|
|
|
return false;
|
|
|
|
|
2009-09-09 15:08:12 +00:00
|
|
|
for (const DeclContext *DC = getDeclContext();
|
2009-03-31 16:35:03 +00:00
|
|
|
DC->isNamespace();
|
|
|
|
DC = DC->getParent()) {
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *Namespace = cast<NamespaceDecl>(DC)) {
|
2009-03-31 16:35:03 +00:00
|
|
|
if (!Namespace->getDeclName())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-01-17 01:30:42 +00:00
|
|
|
bool FunctionDecl::isNoReturn() const {
|
2016-08-17 16:42:15 +00:00
|
|
|
if (hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() ||
|
|
|
|
hasAttr<C11NoReturnAttr>())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (auto *FnTy = getType()->getAs<FunctionType>())
|
|
|
|
return FnTy->getNoReturnAttr();
|
|
|
|
|
|
|
|
return false;
|
2013-01-17 01:30:42 +00:00
|
|
|
}
|
|
|
|
|
2023-03-30 23:07:55 +00:00
|
|
|
bool FunctionDecl::isMemberLikeConstrainedFriend() const {
|
|
|
|
// C++20 [temp.friend]p9:
|
|
|
|
// A non-template friend declaration with a requires-clause [or]
|
|
|
|
// a friend function template with a constraint that depends on a template
|
|
|
|
// parameter from an enclosing template [...] does not declare the same
|
|
|
|
// function or function template as a declaration in any other scope.
|
|
|
|
|
|
|
|
// If this isn't a friend then it's not a member-like constrained friend.
|
|
|
|
if (!getFriendObjectKind()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!getDescribedFunctionTemplate()) {
|
|
|
|
// If these friends don't have constraints, they aren't constrained, and
|
|
|
|
// thus don't fall under temp.friend p9. Else the simple presence of a
|
|
|
|
// constraint makes them unique.
|
|
|
|
return getTrailingRequiresClause();
|
|
|
|
}
|
|
|
|
|
|
|
|
return FriendConstraintRefersToEnclosingTemplate();
|
|
|
|
}
|
2018-11-28 18:34:14 +00:00
|
|
|
|
|
|
|
MultiVersionKind FunctionDecl::getMultiVersionKind() const {
|
|
|
|
if (hasAttr<TargetAttr>())
|
|
|
|
return MultiVersionKind::Target;
|
2022-12-21 11:29:53 +00:00
|
|
|
if (hasAttr<TargetVersionAttr>())
|
|
|
|
return MultiVersionKind::TargetVersion;
|
2018-11-28 18:34:14 +00:00
|
|
|
if (hasAttr<CPUDispatchAttr>())
|
|
|
|
return MultiVersionKind::CPUDispatch;
|
|
|
|
if (hasAttr<CPUSpecificAttr>())
|
|
|
|
return MultiVersionKind::CPUSpecific;
|
2021-11-29 14:28:02 +00:00
|
|
|
if (hasAttr<TargetClonesAttr>())
|
|
|
|
return MultiVersionKind::TargetClones;
|
2018-11-28 18:34:14 +00:00
|
|
|
return MultiVersionKind::None;
|
|
|
|
}
|
|
|
|
|
2018-07-20 14:13:28 +00:00
|
|
|
bool FunctionDecl::isCPUDispatchMultiVersion() const {
|
|
|
|
return isMultiVersion() && hasAttr<CPUDispatchAttr>();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FunctionDecl::isCPUSpecificMultiVersion() const {
|
|
|
|
return isMultiVersion() && hasAttr<CPUSpecificAttr>();
|
|
|
|
}
|
|
|
|
|
2018-10-25 18:57:19 +00:00
|
|
|
bool FunctionDecl::isTargetMultiVersion() const {
|
2022-12-21 11:29:53 +00:00
|
|
|
return isMultiVersion() &&
|
|
|
|
(hasAttr<TargetAttr>() || hasAttr<TargetVersionAttr>());
|
2018-10-25 18:57:19 +00:00
|
|
|
}
|
|
|
|
|
2021-11-29 14:28:02 +00:00
|
|
|
bool FunctionDecl::isTargetClonesMultiVersion() const {
|
|
|
|
return isMultiVersion() && hasAttr<TargetClonesAttr>();
|
|
|
|
}
|
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
void
|
|
|
|
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
|
2013-10-17 15:37:26 +00:00
|
|
|
redeclarable_base::setPreviousDecl(PrevDecl);
|
2010-01-26 22:01:41 +00:00
|
|
|
|
|
|
|
if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
|
|
|
|
FunctionTemplateDecl *PrevFunTmpl
|
2014-05-12 05:36:57 +00:00
|
|
|
= PrevDecl? PrevDecl->getDescribedFunctionTemplate() : nullptr;
|
2010-01-26 22:01:41 +00:00
|
|
|
assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch");
|
2013-10-17 15:37:26 +00:00
|
|
|
FunTmpl->setPreviousDecl(PrevFunTmpl);
|
2010-01-26 22:01:41 +00:00
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2018-08-01 21:02:40 +00:00
|
|
|
if (PrevDecl && PrevDecl->isInlined())
|
|
|
|
setImplicitlyInline(true);
|
2010-01-26 22:01:41 +00:00
|
|
|
}
|
|
|
|
|
2013-10-17 15:37:26 +00:00
|
|
|
FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); }
|
2010-01-26 22:01:41 +00:00
|
|
|
|
2019-03-18 19:23:45 +00:00
|
|
|
/// Returns a value indicating whether this function corresponds to a builtin
|
|
|
|
/// function.
|
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
|
|
|
///
|
2019-03-18 19:23:45 +00:00
|
|
|
/// 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 \c [1,Builtin::First), or a target-specific builtin
|
|
|
|
/// value.
|
|
|
|
///
|
|
|
|
/// \param ConsiderWrapperFunctions If true, we should consider wrapper
|
|
|
|
/// functions as their wrapped builtins. This shouldn't be done in general, but
|
|
|
|
/// it's useful in Sema to diagnose calls to wrappers based on their semantics.
|
|
|
|
unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const {
|
2020-09-04 16:10:09 +00:00
|
|
|
unsigned BuiltinID = 0;
|
[clang] New __attribute__((__clang_arm_mve_alias)).
This allows you to declare a function with a name of your choice (say
`foo`), but have clang treat it as if it were a builtin function (say
`__builtin_foo`), by writing
static __inline__ __attribute__((__clang_arm_mve_alias(__builtin_foo)))
int foo(args);
I'm intending to use this for the ACLE intrinsics for MVE, which have
to be polymorphic on their argument types and also need to be
implemented by builtins. To avoid having to implement the polymorphism
with several layers of nested _Generic and make error reporting
hideous, I want to make all the user-facing intrinsics correspond
directly to clang builtins, so that after clang resolves
__attribute__((overloadable)) polymorphism it's already holding the
right BuiltinID for the intrinsic it selected.
However, this commit itself just introduces the new attribute, and
doesn't use it for anything.
To avoid unanticipated side effects if this attribute is used to make
aliases to other builtins, there's a restriction mechanism: only
(BuiltinID, alias) pairs that are approved by the function
ArmMveAliasValid() will be permitted. At present, that function
doesn't permit anything, because the Tablegen that will generate its
list of valid pairs isn't yet implemented. So the only test of this
facility is one that checks that an unapproved builtin _can't_ be
aliased.
Reviewers: dmgreen, miyuki, ostannard
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D67159
2019-09-02 14:35:09 +00:00
|
|
|
|
[ARM,CDE] Generalize MVE intrinsics infrastructure to support CDE
Summary:
This patch generalizes the existing code to support CDE intrinsics
which will share some properties with existing MVE intrinsics
(some of the intrinsics will be polymorphic and accept/return values
of MVE vector types).
Specifically the patch:
* Adds new tablegen backends -gen-arm-cde-builtin-def,
-gen-arm-cde-builtin-codegen, -gen-arm-cde-builtin-sema,
-gen-arm-cde-builtin-aliases, -gen-arm-cde-builtin-header based on
existing MVE backends.
* Renames the '__clang_arm_mve_alias' attribute into
'__clang_arm_builtin_alias' (it will be used with CDE intrinsics as
well as MVE intrinsics)
* Implements semantic checks for the coprocessor argument of the CDE
intrinsics as well as the existing coprocessor intrinsics.
* Adds one CDE intrinsic __arm_cx1 to test the above changes
Reviewers: simon_tatham, MarkMurrayARM, ostannard, dmgreen
Reviewed By: simon_tatham
Subscribers: sdesmalen, mgorny, kristof.beyls, danielkiss, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D75850
2020-03-10 14:01:42 +00:00
|
|
|
if (const auto *ABAA = getAttr<ArmBuiltinAliasAttr>()) {
|
|
|
|
BuiltinID = ABAA->getBuiltinName()->getBuiltinID();
|
2021-04-16 01:21:01 +00:00
|
|
|
} else if (const auto *BAA = getAttr<BuiltinAliasAttr>()) {
|
|
|
|
BuiltinID = BAA->getBuiltinName()->getBuiltinID();
|
2020-09-04 16:10:09 +00:00
|
|
|
} else if (const auto *A = getAttr<BuiltinAttr>()) {
|
|
|
|
BuiltinID = A->getID();
|
[clang] New __attribute__((__clang_arm_mve_alias)).
This allows you to declare a function with a name of your choice (say
`foo`), but have clang treat it as if it were a builtin function (say
`__builtin_foo`), by writing
static __inline__ __attribute__((__clang_arm_mve_alias(__builtin_foo)))
int foo(args);
I'm intending to use this for the ACLE intrinsics for MVE, which have
to be polymorphic on their argument types and also need to be
implemented by builtins. To avoid having to implement the polymorphism
with several layers of nested _Generic and make error reporting
hideous, I want to make all the user-facing intrinsics correspond
directly to clang builtins, so that after clang resolves
__attribute__((overloadable)) polymorphism it's already holding the
right BuiltinID for the intrinsic it selected.
However, this commit itself just introduces the new attribute, and
doesn't use it for anything.
To avoid unanticipated side effects if this attribute is used to make
aliases to other builtins, there's a restriction mechanism: only
(BuiltinID, alias) pairs that are approved by the function
ArmMveAliasValid() will be permitted. At present, that function
doesn't permit anything, because the Tablegen that will generate its
list of valid pairs isn't yet implemented. So the only test of this
facility is one that checks that an unapproved builtin _can't_ be
aliased.
Reviewers: dmgreen, miyuki, ostannard
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D67159
2019-09-02 14:35:09 +00:00
|
|
|
}
|
2009-02-14 18:57:46 +00:00
|
|
|
|
2012-03-06 23:52:37 +00:00
|
|
|
if (!BuiltinID)
|
|
|
|
return 0;
|
|
|
|
|
2013-11-01 23:46:51 +00:00
|
|
|
// If the function is marked "overloadable", it has a different mangled name
|
|
|
|
// and is not the C library function.
|
[clang] New __attribute__((__clang_arm_mve_alias)).
This allows you to declare a function with a name of your choice (say
`foo`), but have clang treat it as if it were a builtin function (say
`__builtin_foo`), by writing
static __inline__ __attribute__((__clang_arm_mve_alias(__builtin_foo)))
int foo(args);
I'm intending to use this for the ACLE intrinsics for MVE, which have
to be polymorphic on their argument types and also need to be
implemented by builtins. To avoid having to implement the polymorphism
with several layers of nested _Generic and make error reporting
hideous, I want to make all the user-facing intrinsics correspond
directly to clang builtins, so that after clang resolves
__attribute__((overloadable)) polymorphism it's already holding the
right BuiltinID for the intrinsic it selected.
However, this commit itself just introduces the new attribute, and
doesn't use it for anything.
To avoid unanticipated side effects if this attribute is used to make
aliases to other builtins, there's a restriction mechanism: only
(BuiltinID, alias) pairs that are approved by the function
ArmMveAliasValid() will be permitted. At present, that function
doesn't permit anything, because the Tablegen that will generate its
list of valid pairs isn't yet implemented. So the only test of this
facility is one that checks that an unapproved builtin _can't_ be
aliased.
Reviewers: dmgreen, miyuki, ostannard
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D67159
2019-09-02 14:35:09 +00:00
|
|
|
if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>() &&
|
2021-04-16 01:21:01 +00:00
|
|
|
(!hasAttr<ArmBuiltinAliasAttr>() && !hasAttr<BuiltinAliasAttr>()))
|
2013-11-01 23:46:51 +00:00
|
|
|
return 0;
|
|
|
|
|
2020-09-04 16:10:09 +00:00
|
|
|
ASTContext &Context = getASTContext();
|
2009-02-14 18:57:46 +00:00
|
|
|
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.
|
|
|
|
|
2009-02-17 03:23:10 +00:00
|
|
|
// If this is a static function, it's not a builtin.
|
2021-01-04 22:17:45 +00:00
|
|
|
if (!ConsiderWrapperFunctions && getStorageClass() == SC_Static)
|
2009-02-17 03:23:10 +00:00
|
|
|
return 0;
|
|
|
|
|
2016-02-12 12:07:04 +00:00
|
|
|
// OpenCL v1.2 s6.9.f - The library functions defined in
|
|
|
|
// the C99 standard headers are not available.
|
|
|
|
if (Context.getLangOpts().OpenCL &&
|
|
|
|
Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
|
|
|
|
return 0;
|
|
|
|
|
2018-01-23 19:08:18 +00:00
|
|
|
// CUDA does not have device-side standard library. printf and malloc are the
|
|
|
|
// only special cases that are supported by device-side runtime.
|
|
|
|
if (Context.getLangOpts().CUDA && hasAttr<CUDADeviceAttr>() &&
|
|
|
|
!hasAttr<CUDAHostAttr>() &&
|
|
|
|
!(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc))
|
|
|
|
return 0;
|
|
|
|
|
[OpenMP][AMDGCN] Support OpenMP offloading for AMDGCN architecture - Part 1
Summary:
Allow AMDGCN as a GPU offloading target for OpenMP during compiler
invocation and allow setting CUDAMode for it.
Originally authored by Greg Rodgers (@gregrodgers).
Reviewers: ronlieb, yaxunl, b-sumner, scchan, JonChesterfield, jdoerfert, sameerds, msearles, hliao, arsenm
Reviewed By: sameerds
Subscribers: sstefan1, jvesely, wdng, arsenm, guansong, dexonsmith, cfe-commits, llvm-commits, gregrodgers
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D79754
2020-05-14 06:09:04 +00:00
|
|
|
// As AMDGCN implementation of OpenMP does not have a device-side standard
|
|
|
|
// library, none of the predefined library functions except printf and malloc
|
|
|
|
// should be treated as a builtin i.e. 0 should be returned for them.
|
|
|
|
if (Context.getTargetInfo().getTriple().isAMDGCN() &&
|
2023-07-06 09:28:24 +00:00
|
|
|
Context.getLangOpts().OpenMPIsTargetDevice &&
|
[OpenMP][AMDGCN] Support OpenMP offloading for AMDGCN architecture - Part 1
Summary:
Allow AMDGCN as a GPU offloading target for OpenMP during compiler
invocation and allow setting CUDAMode for it.
Originally authored by Greg Rodgers (@gregrodgers).
Reviewers: ronlieb, yaxunl, b-sumner, scchan, JonChesterfield, jdoerfert, sameerds, msearles, hliao, arsenm
Reviewed By: sameerds
Subscribers: sstefan1, jvesely, wdng, arsenm, guansong, dexonsmith, cfe-commits, llvm-commits, gregrodgers
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D79754
2020-05-14 06:09:04 +00:00
|
|
|
Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) &&
|
|
|
|
!(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc))
|
|
|
|
return 0;
|
|
|
|
|
2013-11-01 23:46:51 +00:00
|
|
|
return BuiltinID;
|
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
|
|
|
}
|
|
|
|
|
2009-04-25 06:03:53 +00:00
|
|
|
/// getNumParams - Return the number of parameters this function must have
|
2011-01-10 18:23:55 +00:00
|
|
|
/// based on its FunctionType. This is the length of the ParamInfo array
|
2009-04-25 06:03:53 +00:00
|
|
|
/// after it has been created.
|
|
|
|
unsigned FunctionDecl::getNumParams() const {
|
2015-11-09 17:53:06 +00:00
|
|
|
const auto *FPT = getType()->getAs<FunctionProtoType>();
|
2014-01-20 20:26:09 +00:00
|
|
|
return FPT ? FPT->getNumParams() : 0;
|
2007-01-21 07:42:07 +00:00
|
|
|
}
|
|
|
|
|
2010-09-08 19:31:22 +00:00
|
|
|
void FunctionDecl::setParams(ASTContext &C,
|
2013-01-12 19:30:44 +00:00
|
|
|
ArrayRef<ParmVarDecl *> NewParamInfo) {
|
2014-05-12 05:36:57 +00:00
|
|
|
assert(!ParamInfo && "Already has param info!");
|
2011-09-21 18:16:56 +00:00
|
|
|
assert(NewParamInfo.size() == getNumParams() && "Parameter count mismatch!");
|
2009-09-09 15:08:12 +00:00
|
|
|
|
2007-01-21 19:04:10 +00:00
|
|
|
// Zero params -> null pointer.
|
2011-09-21 18:16:56 +00:00
|
|
|
if (!NewParamInfo.empty()) {
|
|
|
|
ParamInfo = new (C) ParmVarDecl*[NewParamInfo.size()];
|
|
|
|
std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo);
|
2007-01-21 19:04:10 +00:00
|
|
|
}
|
2007-01-21 07:42:07 +00:00
|
|
|
}
|
2007-01-25 04:52:46 +00:00
|
|
|
|
2008-04-10 02:22:51 +00:00
|
|
|
/// 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
|
2014-04-01 19:18:16 +00:00
|
|
|
/// arguments (in C++) or are parameter packs (C++11).
|
2008-04-10 02:22:51 +00:00
|
|
|
unsigned FunctionDecl::getMinRequiredArguments() const {
|
2012-03-11 07:00:24 +00:00
|
|
|
if (!getASTContext().getLangOpts().CPlusPlus)
|
2011-01-11 01:52:23 +00:00
|
|
|
return getNumParams();
|
2014-04-01 19:18:16 +00:00
|
|
|
|
2020-06-02 17:42:36 +00:00
|
|
|
// Note that it is possible for a parameter with no default argument to
|
|
|
|
// follow a parameter with a default argument.
|
2014-04-01 19:18:16 +00:00
|
|
|
unsigned NumRequiredArgs = 0;
|
2020-06-02 17:42:36 +00:00
|
|
|
unsigned MinParamsSoFar = 0;
|
|
|
|
for (auto *Param : parameters()) {
|
|
|
|
if (!Param->isParameterPack()) {
|
|
|
|
++MinParamsSoFar;
|
|
|
|
if (!Param->hasDefaultArg())
|
|
|
|
NumRequiredArgs = MinParamsSoFar;
|
|
|
|
}
|
|
|
|
}
|
2008-04-10 02:22:51 +00:00
|
|
|
return NumRequiredArgs;
|
|
|
|
}
|
|
|
|
|
2022-01-27 12:55:08 +00:00
|
|
|
bool FunctionDecl::hasCXXExplicitFunctionObjectParameter() const {
|
|
|
|
return getNumParams() != 0 && getParamDecl(0)->isExplicitObjectParameter();
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned FunctionDecl::getNumNonObjectParams() const {
|
|
|
|
return getNumParams() -
|
|
|
|
static_cast<unsigned>(hasCXXExplicitFunctionObjectParameter());
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned FunctionDecl::getMinRequiredExplicitArguments() const {
|
|
|
|
return getMinRequiredArguments() -
|
|
|
|
static_cast<unsigned>(hasCXXExplicitFunctionObjectParameter());
|
|
|
|
}
|
|
|
|
|
2020-06-02 17:42:36 +00:00
|
|
|
bool FunctionDecl::hasOneParamOrDefaultArgs() const {
|
|
|
|
return getNumParams() == 1 ||
|
|
|
|
(getNumParams() > 1 &&
|
2022-08-14 23:25:36 +00:00
|
|
|
llvm::all_of(llvm::drop_begin(parameters()),
|
|
|
|
[](ParmVarDecl *P) { return P->hasDefaultArg(); }));
|
2020-06-02 17:42:36 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// The combination of the extern and inline keywords under MSVC forces
|
2014-04-02 23:17:29 +00:00
|
|
|
/// the function to be required.
|
|
|
|
///
|
|
|
|
/// Note: This function assumes that we will only get called when isInlined()
|
|
|
|
/// would return true for this FunctionDecl.
|
|
|
|
bool FunctionDecl::isMSExternInline() const {
|
|
|
|
assert(isInlined() && "expected to get called on an inlined function!");
|
|
|
|
|
|
|
|
const ASTContext &Context = getASTContext();
|
2015-10-08 04:53:31 +00:00
|
|
|
if (!Context.getTargetInfo().getCXXABI().isMicrosoft() &&
|
|
|
|
!hasAttr<DLLExportAttr>())
|
2014-04-02 23:17:29 +00:00
|
|
|
return false;
|
|
|
|
|
2015-03-20 00:02:27 +00:00
|
|
|
for (const FunctionDecl *FD = getMostRecentDecl(); FD;
|
|
|
|
FD = FD->getPreviousDecl())
|
2021-01-04 22:17:45 +00:00
|
|
|
if (!FD->isImplicit() && FD->getStorageClass() == SC_Extern)
|
2014-04-02 23:17:29 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool redeclForcesDefMSVC(const FunctionDecl *Redecl) {
|
2021-01-04 22:17:45 +00:00
|
|
|
if (Redecl->getStorageClass() != SC_Extern)
|
2014-04-02 23:17:29 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
for (const FunctionDecl *FD = Redecl->getPreviousDecl(); FD;
|
|
|
|
FD = FD->getPreviousDecl())
|
2021-01-04 22:17:45 +00:00
|
|
|
if (!FD->isImplicit() && FD->getStorageClass() == SC_Extern)
|
2014-04-02 23:17:29 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-02-07 03:50:18 +00:00
|
|
|
static bool RedeclForcesDefC99(const FunctionDecl *Redecl) {
|
|
|
|
// Only consider file-scope declarations in this test.
|
|
|
|
if (!Redecl->getLexicalDeclContext()->isTranslationUnit())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Only consider explicit declarations; the presence of a builtin for a
|
|
|
|
// libcall shouldn't affect whether a definition is externally visible.
|
|
|
|
if (Redecl->isImplicit())
|
|
|
|
return false;
|
|
|
|
|
2021-01-04 22:17:45 +00:00
|
|
|
if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern)
|
2012-02-07 03:50:18 +00:00
|
|
|
return true; // Not an inline definition
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// For a function declaration in C or C++, determine whether this
|
2011-07-18 05:26:13 +00:00
|
|
|
/// declaration causes the definition to be externally visible.
|
|
|
|
///
|
2014-04-02 23:17:29 +00:00
|
|
|
/// For instance, this determines if adding the current declaration to the set
|
2012-02-07 03:50:18 +00:00
|
|
|
/// of redeclarations of the given functions causes
|
|
|
|
/// isInlineDefinitionExternallyVisible to change from false to true.
|
2011-07-18 05:26:13 +00:00
|
|
|
bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const {
|
2016-10-28 16:46:39 +00:00
|
|
|
assert(!doesThisDeclarationHaveABody() &&
|
2011-07-18 05:26:13 +00:00
|
|
|
"Must have a declaration without a body.");
|
|
|
|
|
|
|
|
ASTContext &Context = getASTContext();
|
|
|
|
|
2014-04-02 23:17:29 +00:00
|
|
|
if (Context.getLangOpts().MSVCCompat) {
|
|
|
|
const FunctionDecl *Definition;
|
|
|
|
if (hasBody(Definition) && Definition->isInlined() &&
|
|
|
|
redeclForcesDefMSVC(this))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-09-27 12:25:19 +00:00
|
|
|
if (Context.getLangOpts().CPlusPlus)
|
|
|
|
return false;
|
|
|
|
|
2012-03-11 07:00:24 +00:00
|
|
|
if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) {
|
2012-02-07 03:50:18 +00:00
|
|
|
// With GNU inlining, a declaration with 'inline' but not 'extern', forces
|
|
|
|
// an externally visible definition.
|
|
|
|
//
|
|
|
|
// FIXME: What happens if gnu_inline gets added on after the first
|
|
|
|
// declaration?
|
2021-01-04 22:17:45 +00:00
|
|
|
if (!isInlineSpecified() || getStorageClass() == SC_Extern)
|
2012-02-07 03:50:18 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
const FunctionDecl *Prev = this;
|
|
|
|
bool FoundBody = false;
|
|
|
|
while ((Prev = Prev->getPreviousDecl())) {
|
2019-12-05 21:37:35 +00:00
|
|
|
FoundBody |= Prev->doesThisDeclarationHaveABody();
|
2012-02-07 03:50:18 +00:00
|
|
|
|
2019-12-05 21:37:35 +00:00
|
|
|
if (Prev->doesThisDeclarationHaveABody()) {
|
2012-02-07 03:50:18 +00:00
|
|
|
// If it's not the case that both 'inline' and 'extern' are
|
|
|
|
// specified on the definition, then it is always externally visible.
|
|
|
|
if (!Prev->isInlineSpecified() ||
|
2021-01-04 22:17:45 +00:00
|
|
|
Prev->getStorageClass() != SC_Extern)
|
2012-02-07 03:50:18 +00:00
|
|
|
return false;
|
2018-07-30 19:24:48 +00:00
|
|
|
} else if (Prev->isInlineSpecified() &&
|
2021-01-04 22:17:45 +00:00
|
|
|
Prev->getStorageClass() != SC_Extern) {
|
2012-02-07 03:50:18 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FoundBody;
|
|
|
|
}
|
|
|
|
|
|
|
|
// C99 6.7.4p6:
|
2018-07-30 19:24:48 +00:00
|
|
|
// [...] If all of the file scope declarations for a function in a
|
|
|
|
// translation unit include the inline function specifier without extern,
|
2012-02-07 03:50:18 +00:00
|
|
|
// then the definition in that translation unit is an inline definition.
|
2021-01-04 22:17:45 +00:00
|
|
|
if (isInlineSpecified() && getStorageClass() != SC_Extern)
|
2011-07-18 05:26:13 +00:00
|
|
|
return false;
|
2012-02-07 03:50:18 +00:00
|
|
|
const FunctionDecl *Prev = this;
|
|
|
|
bool FoundBody = false;
|
|
|
|
while ((Prev = Prev->getPreviousDecl())) {
|
2019-12-05 21:37:35 +00:00
|
|
|
FoundBody |= Prev->doesThisDeclarationHaveABody();
|
2012-02-07 03:50:18 +00:00
|
|
|
if (RedeclForcesDefC99(Prev))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return FoundBody;
|
2011-07-18 05:26:13 +00:00
|
|
|
}
|
|
|
|
|
2019-10-23 00:44:08 +00:00
|
|
|
FunctionTypeLoc FunctionDecl::getFunctionTypeLoc() const {
|
2014-07-02 01:47:15 +00:00
|
|
|
const TypeSourceInfo *TSI = getTypeSourceInfo();
|
2019-10-23 00:44:08 +00:00
|
|
|
return TSI ? TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>()
|
|
|
|
: FunctionTypeLoc();
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceRange FunctionDecl::getReturnTypeSourceRange() const {
|
|
|
|
FunctionTypeLoc FTL = getFunctionTypeLoc();
|
2014-07-02 12:55:58 +00:00
|
|
|
if (!FTL)
|
2014-07-02 01:47:15 +00:00
|
|
|
return SourceRange();
|
|
|
|
|
2014-07-02 12:55:58 +00:00
|
|
|
// Skip self-referential return types.
|
|
|
|
const SourceManager &SM = getASTContext().getSourceManager();
|
|
|
|
SourceRange RTRange = FTL.getReturnLoc().getSourceRange();
|
2018-08-09 21:08:08 +00:00
|
|
|
SourceLocation Boundary = getNameInfo().getBeginLoc();
|
2014-07-02 12:55:58 +00:00
|
|
|
if (RTRange.isInvalid() || Boundary.isInvalid() ||
|
|
|
|
!SM.isBeforeInTranslationUnit(RTRange.getEnd(), Boundary))
|
|
|
|
return SourceRange();
|
2014-07-02 01:47:15 +00:00
|
|
|
|
2014-07-02 12:55:58 +00:00
|
|
|
return RTRange;
|
2014-07-02 01:47:15 +00:00
|
|
|
}
|
|
|
|
|
2019-12-03 13:21:55 +00:00
|
|
|
SourceRange FunctionDecl::getParametersSourceRange() const {
|
|
|
|
unsigned NP = getNumParams();
|
|
|
|
SourceLocation EllipsisLoc = getEllipsisLoc();
|
|
|
|
|
|
|
|
if (NP == 0 && EllipsisLoc.isInvalid())
|
|
|
|
return SourceRange();
|
|
|
|
|
|
|
|
SourceLocation Begin =
|
|
|
|
NP > 0 ? ParamInfo[0]->getSourceRange().getBegin() : EllipsisLoc;
|
|
|
|
SourceLocation End = EllipsisLoc.isValid()
|
|
|
|
? EllipsisLoc
|
|
|
|
: ParamInfo[NP - 1]->getSourceRange().getEnd();
|
|
|
|
|
|
|
|
return SourceRange(Begin, End);
|
|
|
|
}
|
|
|
|
|
2017-01-12 16:11:28 +00:00
|
|
|
SourceRange FunctionDecl::getExceptionSpecSourceRange() const {
|
2019-10-23 00:44:08 +00:00
|
|
|
FunctionTypeLoc FTL = getFunctionTypeLoc();
|
|
|
|
return FTL ? FTL.getExceptionSpecRange() : SourceRange();
|
2017-01-12 16:11:28 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// For an inline function definition in C, or for a gnu_inline function
|
2013-01-25 00:08:28 +00:00
|
|
|
/// in C++, determine whether the definition will be externally visible.
|
2009-09-13 07:46:26 +00:00
|
|
|
///
|
|
|
|
/// 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
|
2009-09-13 07:46:26 +00:00
|
|
|
/// inline definition becomes externally visible (C99 6.7.4p6).
|
|
|
|
///
|
|
|
|
/// In GNU89 mode, or if the gnu_inline attribute is attached to the function
|
2018-07-30 19:24:48 +00:00
|
|
|
/// 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
|
2009-09-13 07:46:26 +00:00
|
|
|
/// externally visible symbol.
|
|
|
|
bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
|
2019-09-12 19:53:35 +00:00
|
|
|
assert((doesThisDeclarationHaveABody() || willHaveBody() ||
|
|
|
|
hasAttr<AliasAttr>()) &&
|
2016-11-01 10:30:50 +00:00
|
|
|
"Must be a function definition");
|
2009-10-27 21:11:48 +00:00
|
|
|
assert(isInlined() && "Function must be inline");
|
2009-10-27 23:26:40 +00:00
|
|
|
ASTContext &Context = getASTContext();
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2012-03-11 07:00:24 +00:00
|
|
|
if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) {
|
2012-02-07 03:50:18 +00:00
|
|
|
// Note: If you change the logic here, please change
|
|
|
|
// doesDeclarationForceExternallyVisibleDefinition as well.
|
|
|
|
//
|
2010-12-09 16:59:22 +00:00
|
|
|
// If it's not the case that both 'inline' and 'extern' are
|
|
|
|
// specified on the definition, then this inline definition is
|
|
|
|
// externally visible.
|
2019-09-27 12:25:19 +00:00
|
|
|
if (Context.getLangOpts().CPlusPlus)
|
|
|
|
return false;
|
2021-01-04 22:17:45 +00:00
|
|
|
if (!(isInlineSpecified() && getStorageClass() == SC_Extern))
|
2010-12-09 16:59:22 +00:00
|
|
|
return true;
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2010-12-09 16:59:22 +00:00
|
|
|
// If any declaration is 'inline' but not 'extern', then this definition
|
|
|
|
// is externally visible.
|
2022-09-04 06:27:27 +00:00
|
|
|
for (auto *Redecl : redecls()) {
|
2018-07-30 19:24:48 +00:00
|
|
|
if (Redecl->isInlineSpecified() &&
|
2021-01-04 22:17:45 +00:00
|
|
|
Redecl->getStorageClass() != SC_Extern)
|
2009-09-13 07:46:26 +00:00
|
|
|
return true;
|
2018-07-30 19:24:48 +00:00
|
|
|
}
|
|
|
|
|
2009-04-28 06:37:30 +00:00
|
|
|
return false;
|
2009-09-13 07:46:26 +00:00
|
|
|
}
|
2012-02-07 03:50:18 +00:00
|
|
|
|
2013-01-25 00:08:28 +00:00
|
|
|
// The rest of this function is C-only.
|
|
|
|
assert(!Context.getLangOpts().CPlusPlus &&
|
|
|
|
"should not use C inline rules in C++");
|
|
|
|
|
2009-09-13 07:46:26 +00:00
|
|
|
// C99 6.7.4p6:
|
2018-07-30 19:24:48 +00:00
|
|
|
// [...] If all of the file scope declarations for a function in a
|
|
|
|
// translation unit include the inline function specifier without extern,
|
2009-09-13 07:46:26 +00:00
|
|
|
// then the definition in that translation unit is an inline definition.
|
2022-09-04 06:27:27 +00:00
|
|
|
for (auto *Redecl : redecls()) {
|
2014-03-06 23:45:36 +00:00
|
|
|
if (RedeclForcesDefC99(Redecl))
|
2012-02-07 03:50:18 +00:00
|
|
|
return true;
|
2009-09-13 07:46:26 +00:00
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2009-09-13 07:46:26 +00:00
|
|
|
// C99 6.7.4p6:
|
2018-07-30 19:24:48 +00:00
|
|
|
// An inline definition does not provide an external definition for the
|
|
|
|
// function, and does not forbid an external definition in another
|
2009-09-13 07:46:26 +00:00
|
|
|
// translation unit.
|
2009-04-28 06:37:30 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-11-06 22:13:31 +00:00
|
|
|
/// getOverloadedOperator - Which C++ overloaded operator this
|
|
|
|
/// function represents, if any.
|
|
|
|
OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
|
Extend DeclarationName to support C++ overloaded operators, e.g.,
operator+, directly, using the same mechanism as all other special
names.
Removed the "special" identifiers for the overloaded operators from
the identifier table and IdentifierInfo data structure. IdentifierInfo
is back to representing only real identifiers.
Added a new Action, ActOnOperatorFunctionIdExpr, that builds an
expression from an parsed operator-function-id (e.g., "operator
+"). ActOnIdentifierExpr used to do this job, but
operator-function-ids are no longer represented by IdentifierInfo's.
Extended Declarator to store overloaded operator names.
Sema::GetNameForDeclarator now knows how to turn the operator
name into a DeclarationName for the overloaded operator.
Except for (perhaps) consolidating the functionality of
ActOnIdentifier, ActOnOperatorFunctionIdExpr, and
ActOnConversionFunctionExpr into a common routine that builds an
appropriate DeclRefExpr by looking up a DeclarationName, all of the
work on normalizing declaration names should be complete with this
commit.
llvm-svn: 59526
2008-11-18 14:39:36 +00:00
|
|
|
if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
|
|
|
|
return getDeclName().getCXXOverloadedOperator();
|
2021-01-25 10:09:56 +00:00
|
|
|
return OO_None;
|
2008-11-06 22:13:31 +00:00
|
|
|
}
|
|
|
|
|
2010-01-13 09:01:02 +00:00
|
|
|
/// getLiteralIdentifier - The literal suffix identifier this function
|
|
|
|
/// represents, if any.
|
|
|
|
const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const {
|
|
|
|
if (getDeclName().getNameKind() == DeclarationName::CXXLiteralOperatorName)
|
|
|
|
return getDeclName().getCXXLiteralIdentifier();
|
2021-01-25 10:09:56 +00:00
|
|
|
return nullptr;
|
2010-01-13 09:01:02 +00:00
|
|
|
}
|
|
|
|
|
2010-06-22 09:54:51 +00:00
|
|
|
FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const {
|
|
|
|
if (TemplateOrSpecialization.isNull())
|
|
|
|
return TK_NonTemplate;
|
2022-07-22 19:30:47 +00:00
|
|
|
if (const auto *ND = TemplateOrSpecialization.dyn_cast<NamedDecl *>()) {
|
|
|
|
if (isa<FunctionDecl>(ND))
|
|
|
|
return TK_DependentNonTemplate;
|
|
|
|
assert(isa<FunctionTemplateDecl>(ND) &&
|
|
|
|
"No other valid types in NamedDecl");
|
2010-06-22 09:54:51 +00:00
|
|
|
return TK_FunctionTemplate;
|
2022-07-22 19:30:47 +00:00
|
|
|
}
|
2010-06-22 09:54:51 +00:00
|
|
|
if (TemplateOrSpecialization.is<MemberSpecializationInfo *>())
|
|
|
|
return TK_MemberSpecialization;
|
|
|
|
if (TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>())
|
|
|
|
return TK_FunctionTemplateSpecialization;
|
|
|
|
if (TemplateOrSpecialization.is
|
|
|
|
<DependentFunctionTemplateSpecializationInfo*>())
|
|
|
|
return TK_DependentFunctionTemplateSpecialization;
|
|
|
|
|
2011-09-23 05:06:16 +00:00
|
|
|
llvm_unreachable("Did we miss a TemplateOrSpecialization type?");
|
2010-06-22 09:54:51 +00:00
|
|
|
}
|
|
|
|
|
2009-10-07 23:56:10 +00:00
|
|
|
FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
|
2009-10-12 20:18:28 +00:00
|
|
|
if (MemberSpecializationInfo *Info = getMemberSpecializationInfo())
|
2009-10-07 23:56:10 +00:00
|
|
|
return cast<FunctionDecl>(Info->getInstantiatedFrom());
|
2014-05-12 05:36:57 +00:00
|
|
|
|
|
|
|
return nullptr;
|
2009-10-07 23:56:10 +00:00
|
|
|
}
|
|
|
|
|
2015-12-30 03:24:14 +00:00
|
|
|
MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const {
|
2019-05-02 00:49:14 +00:00
|
|
|
if (auto *MSI =
|
|
|
|
TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
|
|
|
|
return MSI;
|
|
|
|
if (auto *FTSI = TemplateOrSpecialization
|
|
|
|
.dyn_cast<FunctionTemplateSpecializationInfo *>())
|
|
|
|
return FTSI->getMemberSpecializationInfo();
|
|
|
|
return nullptr;
|
2015-12-30 03:24:14 +00:00
|
|
|
}
|
|
|
|
|
2018-07-30 19:24:48 +00:00
|
|
|
void
|
2010-09-08 19:31:22 +00:00
|
|
|
FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C,
|
|
|
|
FunctionDecl *FD,
|
2009-10-07 23:56:10 +00:00
|
|
|
TemplateSpecializationKind TSK) {
|
2018-07-30 19:24:48 +00:00
|
|
|
assert(TemplateOrSpecialization.isNull() &&
|
2009-10-07 23:56:10 +00:00
|
|
|
"Member function is already a specialization");
|
2018-07-30 19:24:48 +00:00
|
|
|
MemberSpecializationInfo *Info
|
2010-09-08 19:31:22 +00:00
|
|
|
= new (C) MemberSpecializationInfo(FD, TSK);
|
2009-10-07 23:56:10 +00:00
|
|
|
TemplateOrSpecialization = Info;
|
|
|
|
}
|
|
|
|
|
2015-12-30 03:24:14 +00:00
|
|
|
FunctionTemplateDecl *FunctionDecl::getDescribedFunctionTemplate() const {
|
2023-09-13 12:53:27 +00:00
|
|
|
return dyn_cast_if_present<FunctionTemplateDecl>(
|
2022-07-22 19:30:47 +00:00
|
|
|
TemplateOrSpecialization.dyn_cast<NamedDecl *>());
|
2015-12-30 03:24:14 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 19:30:47 +00:00
|
|
|
void FunctionDecl::setDescribedFunctionTemplate(
|
|
|
|
FunctionTemplateDecl *Template) {
|
2019-05-02 00:49:14 +00:00
|
|
|
assert(TemplateOrSpecialization.isNull() &&
|
|
|
|
"Member function is already a specialization");
|
2022-05-09 16:04:17 +00:00
|
|
|
TemplateOrSpecialization = Template;
|
2015-12-30 03:24:14 +00:00
|
|
|
}
|
|
|
|
|
2023-10-07 06:55:31 +00:00
|
|
|
bool FunctionDecl::isFunctionTemplateSpecialization() const {
|
|
|
|
return TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>() ||
|
|
|
|
TemplateOrSpecialization
|
|
|
|
.is<DependentFunctionTemplateSpecializationInfo *>();
|
|
|
|
}
|
|
|
|
|
2022-07-22 19:30:47 +00:00
|
|
|
void FunctionDecl::setInstantiatedFromDecl(FunctionDecl *FD) {
|
|
|
|
assert(TemplateOrSpecialization.isNull() &&
|
|
|
|
"Function is already a specialization");
|
|
|
|
TemplateOrSpecialization = FD;
|
|
|
|
}
|
|
|
|
|
|
|
|
FunctionDecl *FunctionDecl::getInstantiatedFromDecl() const {
|
2023-09-13 12:53:27 +00:00
|
|
|
return dyn_cast_if_present<FunctionDecl>(
|
2022-07-22 19:30:47 +00:00
|
|
|
TemplateOrSpecialization.dyn_cast<NamedDecl *>());
|
|
|
|
}
|
|
|
|
|
2009-10-27 20:53:28 +00:00
|
|
|
bool FunctionDecl::isImplicitlyInstantiable() const {
|
2010-05-17 17:34:56 +00:00
|
|
|
// If the function is invalid, it can't be implicitly instantiated.
|
|
|
|
if (isInvalidDecl())
|
2009-10-27 20:53:28 +00:00
|
|
|
return false;
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2019-05-02 00:49:14 +00:00
|
|
|
switch (getTemplateSpecializationKindForInstantiation()) {
|
2009-10-27 20:53:28 +00:00
|
|
|
case TSK_Undeclared:
|
|
|
|
case TSK_ExplicitInstantiationDefinition:
|
2019-05-02 00:49:14 +00:00
|
|
|
case TSK_ExplicitSpecialization:
|
2009-10-27 20:53:28 +00:00
|
|
|
return false;
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2009-10-27 20:53:28 +00:00
|
|
|
case TSK_ImplicitInstantiation:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case TSK_ExplicitInstantiationDeclaration:
|
|
|
|
// Handled below.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the actual template from which we will instantiate.
|
|
|
|
const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
|
2010-07-07 11:31:19 +00:00
|
|
|
bool HasPattern = false;
|
2009-10-27 20:53:28 +00:00
|
|
|
if (PatternDecl)
|
2010-07-07 11:31:19 +00:00
|
|
|
HasPattern = PatternDecl->hasBody(PatternDecl);
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2009-10-27 20:53:28 +00:00
|
|
|
// C++0x [temp.explicit]p9:
|
|
|
|
// Except for inline functions, other explicit instantiation declarations
|
|
|
|
// have the effect of suppressing the implicit instantiation of the entity
|
2018-07-30 19:24:48 +00:00
|
|
|
// to which they refer.
|
|
|
|
if (!HasPattern || !PatternDecl)
|
2009-10-27 20:53:28 +00:00
|
|
|
return true;
|
|
|
|
|
2009-10-27 21:11:48 +00:00
|
|
|
return PatternDecl->isInlined();
|
2011-12-01 00:59:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool FunctionDecl::isTemplateInstantiation() const {
|
2019-05-02 00:49:14 +00:00
|
|
|
// FIXME: Remove this, it's not clear what it means. (Which template
|
|
|
|
// specialization kind?)
|
|
|
|
return clang::isTemplateInstantiation(getTemplateSpecializationKind());
|
2011-12-01 00:59:17 +00:00
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2020-07-09 21:57:30 +00:00
|
|
|
FunctionDecl *
|
|
|
|
FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const {
|
2018-07-30 19:24:48 +00:00
|
|
|
// If this is a generic lambda call operator specialization, its
|
2014-04-03 16:32:21 +00:00
|
|
|
// instantiation pattern is always its primary template's pattern
|
2018-07-30 19:24:48 +00:00
|
|
|
// even if its primary template was instantiated from another
|
2014-04-03 16:32:21 +00:00
|
|
|
// member template (which happens with nested generic lambdas).
|
2018-07-30 19:24:48 +00:00
|
|
|
// Since a lambda's call operator's body is transformed eagerly,
|
|
|
|
// we don't have to go hunting for a prototype definition template
|
|
|
|
// (i.e. instantiated-from-member-template) to use as an instantiation
|
2014-04-03 16:32:21 +00:00
|
|
|
// pattern.
|
|
|
|
|
|
|
|
if (isGenericLambdaCallOperatorSpecialization(
|
|
|
|
dyn_cast<CXXMethodDecl>(this))) {
|
2017-04-21 01:15:13 +00:00
|
|
|
assert(getPrimaryTemplate() && "not a generic lambda call operator?");
|
|
|
|
return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl());
|
2014-04-03 16:32:21 +00:00
|
|
|
}
|
2017-04-21 01:15:13 +00:00
|
|
|
|
2020-10-31 01:30:56 +00:00
|
|
|
// Check for a declaration of this function that was instantiated from a
|
|
|
|
// friend definition.
|
|
|
|
const FunctionDecl *FD = nullptr;
|
|
|
|
if (!isDefined(FD, /*CheckForPendingFriendDefinition=*/true))
|
|
|
|
FD = this;
|
|
|
|
|
|
|
|
if (MemberSpecializationInfo *Info = FD->getMemberSpecializationInfo()) {
|
2020-07-09 21:57:30 +00:00
|
|
|
if (ForDefinition &&
|
|
|
|
!clang::isTemplateInstantiation(Info->getTemplateSpecializationKind()))
|
2019-05-02 00:49:14 +00:00
|
|
|
return nullptr;
|
|
|
|
return getDefinitionOrSelf(cast<FunctionDecl>(Info->getInstantiatedFrom()));
|
|
|
|
}
|
|
|
|
|
2020-07-09 21:57:30 +00:00
|
|
|
if (ForDefinition &&
|
|
|
|
!clang::isTemplateInstantiation(getTemplateSpecializationKind()))
|
2019-05-02 00:49:14 +00:00
|
|
|
return nullptr;
|
|
|
|
|
2009-10-27 20:53:28 +00:00
|
|
|
if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
|
2019-05-03 23:51:38 +00:00
|
|
|
// If we hit a point where the user provided a specialization of this
|
|
|
|
// template, we're done looking.
|
2020-07-09 21:57:30 +00:00
|
|
|
while (!ForDefinition || !Primary->isMemberSpecialization()) {
|
2019-05-03 23:51:38 +00:00
|
|
|
auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate();
|
|
|
|
if (!NewPrimary)
|
2009-10-27 20:53:28 +00:00
|
|
|
break;
|
2019-05-03 23:51:38 +00:00
|
|
|
Primary = NewPrimary;
|
2009-10-27 20:53:28 +00:00
|
|
|
}
|
2017-04-21 01:15:13 +00:00
|
|
|
|
|
|
|
return getDefinitionOrSelf(Primary->getTemplatedDecl());
|
2018-07-30 19:24:48 +00:00
|
|
|
}
|
2017-04-21 01:15:13 +00:00
|
|
|
|
|
|
|
return nullptr;
|
2009-10-27 20:53:28 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 17:30:29 +00:00
|
|
|
FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
|
2009-09-09 15:08:12 +00:00
|
|
|
if (FunctionTemplateSpecializationInfo *Info
|
2009-06-29 17:30:29 +00:00
|
|
|
= TemplateOrSpecialization
|
|
|
|
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
|
2019-05-02 00:49:14 +00:00
|
|
|
return Info->getTemplate();
|
2009-06-29 17:30:29 +00:00
|
|
|
}
|
2014-05-12 05:36:57 +00:00
|
|
|
return nullptr;
|
2009-06-29 17:30:29 +00:00
|
|
|
}
|
|
|
|
|
2015-12-30 03:24:14 +00:00
|
|
|
FunctionTemplateSpecializationInfo *
|
|
|
|
FunctionDecl::getTemplateSpecializationInfo() const {
|
|
|
|
return TemplateOrSpecialization
|
|
|
|
.dyn_cast<FunctionTemplateSpecializationInfo *>();
|
|
|
|
}
|
|
|
|
|
2009-06-29 17:30:29 +00:00
|
|
|
const TemplateArgumentList *
|
|
|
|
FunctionDecl::getTemplateSpecializationArgs() const {
|
2009-09-09 15:08:12 +00:00
|
|
|
if (FunctionTemplateSpecializationInfo *Info
|
2009-10-13 16:30:37 +00:00
|
|
|
= TemplateOrSpecialization
|
|
|
|
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
|
2009-06-29 17:30:29 +00:00
|
|
|
return Info->TemplateArguments;
|
|
|
|
}
|
2014-05-12 05:36:57 +00:00
|
|
|
return nullptr;
|
2009-06-29 17:30:29 +00:00
|
|
|
}
|
|
|
|
|
2011-09-22 20:07:09 +00:00
|
|
|
const ASTTemplateArgumentListInfo *
|
2010-05-20 15:32:11 +00:00
|
|
|
FunctionDecl::getTemplateSpecializationArgsAsWritten() const {
|
|
|
|
if (FunctionTemplateSpecializationInfo *Info
|
|
|
|
= TemplateOrSpecialization
|
|
|
|
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
|
|
|
|
return Info->TemplateArgumentsAsWritten;
|
|
|
|
}
|
2023-10-07 06:55:31 +00:00
|
|
|
if (DependentFunctionTemplateSpecializationInfo *Info =
|
|
|
|
TemplateOrSpecialization
|
|
|
|
.dyn_cast<DependentFunctionTemplateSpecializationInfo *>()) {
|
|
|
|
return Info->TemplateArgumentsAsWritten;
|
|
|
|
}
|
2014-05-12 05:36:57 +00:00
|
|
|
return nullptr;
|
2010-05-20 15:32:11 +00:00
|
|
|
}
|
|
|
|
|
2009-09-09 15:08:12 +00:00
|
|
|
void
|
2010-09-08 19:31:22 +00:00
|
|
|
FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
|
|
|
|
FunctionTemplateDecl *Template,
|
2009-06-29 20:59:39 +00:00
|
|
|
const TemplateArgumentList *TemplateArgs,
|
2009-09-24 23:14:47 +00:00
|
|
|
void *InsertPos,
|
2010-05-20 15:32:11 +00:00
|
|
|
TemplateSpecializationKind TSK,
|
2010-07-05 10:37:55 +00:00
|
|
|
const TemplateArgumentListInfo *TemplateArgsAsWritten,
|
|
|
|
SourceLocation PointOfInstantiation) {
|
2019-05-02 00:49:14 +00:00
|
|
|
assert((TemplateOrSpecialization.isNull() ||
|
|
|
|
TemplateOrSpecialization.is<MemberSpecializationInfo *>()) &&
|
|
|
|
"Member function is already a specialization");
|
2018-07-30 19:24:48 +00:00
|
|
|
assert(TSK != TSK_Undeclared &&
|
2009-09-24 23:14:47 +00:00
|
|
|
"Must specify the type of function template specialization");
|
2019-05-02 00:49:14 +00:00
|
|
|
assert((TemplateOrSpecialization.isNull() ||
|
|
|
|
TSK == TSK_ExplicitSpecialization) &&
|
|
|
|
"Member specialization must be an explicit specialization");
|
|
|
|
FunctionTemplateSpecializationInfo *Info =
|
|
|
|
FunctionTemplateSpecializationInfo::Create(
|
|
|
|
C, this, Template, TSK, TemplateArgs, TemplateArgsAsWritten,
|
|
|
|
PointOfInstantiation,
|
|
|
|
TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>());
|
2009-06-26 00:10:03 +00:00
|
|
|
TemplateOrSpecialization = Info;
|
2012-03-28 14:34:23 +00:00
|
|
|
Template->addSpecialization(Info, InsertPos);
|
2009-06-26 00:10:03 +00:00
|
|
|
}
|
|
|
|
|
2023-10-07 06:55:31 +00:00
|
|
|
void FunctionDecl::setDependentTemplateSpecialization(
|
|
|
|
ASTContext &Context, const UnresolvedSetImpl &Templates,
|
|
|
|
const TemplateArgumentListInfo *TemplateArgs) {
|
2010-04-08 09:05:18 +00:00
|
|
|
assert(TemplateOrSpecialization.isNull());
|
|
|
|
DependentFunctionTemplateSpecializationInfo *Info =
|
2015-08-06 20:26:32 +00:00
|
|
|
DependentFunctionTemplateSpecializationInfo::Create(Context, Templates,
|
|
|
|
TemplateArgs);
|
2010-04-08 09:05:18 +00:00
|
|
|
TemplateOrSpecialization = Info;
|
|
|
|
}
|
|
|
|
|
2015-12-30 03:24:14 +00:00
|
|
|
DependentFunctionTemplateSpecializationInfo *
|
|
|
|
FunctionDecl::getDependentSpecializationInfo() const {
|
|
|
|
return TemplateOrSpecialization
|
|
|
|
.dyn_cast<DependentFunctionTemplateSpecializationInfo *>();
|
|
|
|
}
|
|
|
|
|
2015-08-06 20:26:32 +00:00
|
|
|
DependentFunctionTemplateSpecializationInfo *
|
|
|
|
DependentFunctionTemplateSpecializationInfo::Create(
|
2023-10-07 06:55:31 +00:00
|
|
|
ASTContext &Context, const UnresolvedSetImpl &Candidates,
|
|
|
|
const TemplateArgumentListInfo *TArgs) {
|
|
|
|
const auto *TArgsWritten =
|
|
|
|
TArgs ? ASTTemplateArgumentListInfo::Create(Context, *TArgs) : nullptr;
|
|
|
|
return new (Context.Allocate(
|
|
|
|
totalSizeToAlloc<FunctionTemplateDecl *>(Candidates.size())))
|
|
|
|
DependentFunctionTemplateSpecializationInfo(Candidates, TArgsWritten);
|
2015-08-06 20:26:32 +00:00
|
|
|
}
|
|
|
|
|
2010-04-08 09:05:18 +00:00
|
|
|
DependentFunctionTemplateSpecializationInfo::
|
2023-10-07 06:55:31 +00:00
|
|
|
DependentFunctionTemplateSpecializationInfo(
|
|
|
|
const UnresolvedSetImpl &Candidates,
|
|
|
|
const ASTTemplateArgumentListInfo *TemplateArgsWritten)
|
2023-10-07 07:33:22 +00:00
|
|
|
: NumCandidates(Candidates.size()),
|
|
|
|
TemplateArgumentsAsWritten(TemplateArgsWritten) {
|
2023-10-07 06:55:31 +00:00
|
|
|
std::transform(Candidates.begin(), Candidates.end(),
|
|
|
|
getTrailingObjects<FunctionTemplateDecl *>(),
|
|
|
|
[](NamedDecl *ND) {
|
|
|
|
return cast<FunctionTemplateDecl>(ND->getUnderlyingDecl());
|
|
|
|
});
|
2010-04-08 09:05:18 +00:00
|
|
|
}
|
|
|
|
|
2009-09-04 22:48:11 +00:00
|
|
|
TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
|
2009-09-09 15:08:12 +00:00
|
|
|
// For a function template specialization, query the specialization
|
2009-09-04 22:48:11 +00:00
|
|
|
// information object.
|
2019-05-02 00:49:14 +00:00
|
|
|
if (FunctionTemplateSpecializationInfo *FTSInfo =
|
|
|
|
TemplateOrSpecialization
|
|
|
|
.dyn_cast<FunctionTemplateSpecializationInfo *>())
|
|
|
|
return FTSInfo->getTemplateSpecializationKind();
|
|
|
|
|
|
|
|
if (MemberSpecializationInfo *MSInfo =
|
|
|
|
TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
|
|
|
|
return MSInfo->getTemplateSpecializationKind();
|
|
|
|
|
2023-10-07 06:55:31 +00:00
|
|
|
// A dependent function template specialization is an explicit specialization,
|
|
|
|
// except when it's a friend declaration.
|
|
|
|
if (TemplateOrSpecialization
|
|
|
|
.is<DependentFunctionTemplateSpecializationInfo *>() &&
|
|
|
|
getFriendObjectKind() == FOK_None)
|
|
|
|
return TSK_ExplicitSpecialization;
|
|
|
|
|
2019-05-02 00:49:14 +00:00
|
|
|
return TSK_Undeclared;
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateSpecializationKind
|
|
|
|
FunctionDecl::getTemplateSpecializationKindForInstantiation() const {
|
|
|
|
// This is the same as getTemplateSpecializationKind(), except that for a
|
|
|
|
// function that is both a function template specialization and a member
|
|
|
|
// specialization, we prefer the member specialization information. Eg:
|
|
|
|
//
|
|
|
|
// template<typename T> struct A {
|
|
|
|
// template<typename U> void f() {}
|
|
|
|
// template<> void f<int>() {}
|
|
|
|
// };
|
|
|
|
//
|
2023-10-07 06:55:31 +00:00
|
|
|
// Within the templated CXXRecordDecl, A<T>::f<int> is a dependent function
|
|
|
|
// template specialization; both getTemplateSpecializationKind() and
|
|
|
|
// getTemplateSpecializationKindForInstantiation() will return
|
|
|
|
// TSK_ExplicitSpecialization.
|
|
|
|
//
|
2019-05-02 00:49:14 +00:00
|
|
|
// For A<int>::f<int>():
|
|
|
|
// * getTemplateSpecializationKind() will return TSK_ExplicitSpecialization
|
|
|
|
// * getTemplateSpecializationKindForInstantiation() will return
|
|
|
|
// TSK_ImplicitInstantiation
|
|
|
|
//
|
|
|
|
// This reflects the facts that A<int>::f<int> is an explicit specialization
|
|
|
|
// of A<int>::f, and that A<int>::f<int> should be implicitly instantiated
|
|
|
|
// from A::f<int> if a definition is needed.
|
|
|
|
if (FunctionTemplateSpecializationInfo *FTSInfo =
|
|
|
|
TemplateOrSpecialization
|
|
|
|
.dyn_cast<FunctionTemplateSpecializationInfo *>()) {
|
|
|
|
if (auto *MSInfo = FTSInfo->getMemberSpecializationInfo())
|
|
|
|
return MSInfo->getTemplateSpecializationKind();
|
2009-10-07 23:56:10 +00:00
|
|
|
return FTSInfo->getTemplateSpecializationKind();
|
2019-05-02 00:49:14 +00:00
|
|
|
}
|
2009-09-04 22:48:11 +00:00
|
|
|
|
2019-05-02 00:49:14 +00:00
|
|
|
if (MemberSpecializationInfo *MSInfo =
|
|
|
|
TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
|
2009-10-07 23:56:10 +00:00
|
|
|
return MSInfo->getTemplateSpecializationKind();
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2023-10-07 06:55:31 +00:00
|
|
|
if (TemplateOrSpecialization
|
|
|
|
.is<DependentFunctionTemplateSpecializationInfo *>() &&
|
|
|
|
getFriendObjectKind() == FOK_None)
|
|
|
|
return TSK_ExplicitSpecialization;
|
|
|
|
|
2009-10-07 23:56:10 +00:00
|
|
|
return TSK_Undeclared;
|
2009-06-29 22:39:32 +00:00
|
|
|
}
|
|
|
|
|
2009-09-09 15:08:12 +00:00
|
|
|
void
|
2009-10-15 17:21:20 +00:00
|
|
|
FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
|
|
|
|
SourceLocation PointOfInstantiation) {
|
2009-10-07 23:56:10 +00:00
|
|
|
if (FunctionTemplateSpecializationInfo *FTSInfo
|
|
|
|
= TemplateOrSpecialization.dyn_cast<
|
2009-10-15 17:21:20 +00:00
|
|
|
FunctionTemplateSpecializationInfo*>()) {
|
2009-10-07 23:56:10 +00:00
|
|
|
FTSInfo->setTemplateSpecializationKind(TSK);
|
2009-10-15 17:21:20 +00:00
|
|
|
if (TSK != TSK_ExplicitSpecialization &&
|
|
|
|
PointOfInstantiation.isValid() &&
|
2017-12-05 01:31:47 +00:00
|
|
|
FTSInfo->getPointOfInstantiation().isInvalid()) {
|
2009-10-15 17:21:20 +00:00
|
|
|
FTSInfo->setPointOfInstantiation(PointOfInstantiation);
|
2017-12-05 01:31:47 +00:00
|
|
|
if (ASTMutationListener *L = getASTContext().getASTMutationListener())
|
|
|
|
L->InstantiationRequested(this);
|
|
|
|
}
|
2009-10-15 17:21:20 +00:00
|
|
|
} else if (MemberSpecializationInfo *MSInfo
|
|
|
|
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) {
|
2009-10-07 23:56:10 +00:00
|
|
|
MSInfo->setTemplateSpecializationKind(TSK);
|
2009-10-15 17:21:20 +00:00
|
|
|
if (TSK != TSK_ExplicitSpecialization &&
|
|
|
|
PointOfInstantiation.isValid() &&
|
2017-12-05 01:31:47 +00:00
|
|
|
MSInfo->getPointOfInstantiation().isInvalid()) {
|
2009-10-15 17:21:20 +00:00
|
|
|
MSInfo->setPointOfInstantiation(PointOfInstantiation);
|
2017-12-05 01:31:47 +00:00
|
|
|
if (ASTMutationListener *L = getASTContext().getASTMutationListener())
|
|
|
|
L->InstantiationRequested(this);
|
|
|
|
}
|
2009-10-15 17:21:20 +00:00
|
|
|
} else
|
2011-09-23 05:06:16 +00:00
|
|
|
llvm_unreachable("Function cannot have a template specialization kind");
|
2009-06-29 22:39:32 +00:00
|
|
|
}
|
|
|
|
|
2009-10-15 17:21:20 +00:00
|
|
|
SourceLocation FunctionDecl::getPointOfInstantiation() const {
|
|
|
|
if (FunctionTemplateSpecializationInfo *FTSInfo
|
|
|
|
= TemplateOrSpecialization.dyn_cast<
|
|
|
|
FunctionTemplateSpecializationInfo*>())
|
|
|
|
return FTSInfo->getPointOfInstantiation();
|
2021-01-25 10:09:56 +00:00
|
|
|
if (MemberSpecializationInfo *MSInfo =
|
|
|
|
TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
|
2009-10-15 17:21:20 +00:00
|
|
|
return MSInfo->getPointOfInstantiation();
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2009-10-15 17:21:20 +00:00
|
|
|
return SourceLocation();
|
|
|
|
}
|
|
|
|
|
2009-09-11 20:15:17 +00:00
|
|
|
bool FunctionDecl::isOutOfLine() const {
|
2011-02-19 18:51:44 +00:00
|
|
|
if (Decl::isOutOfLine())
|
2009-09-11 20:15:17 +00:00
|
|
|
return true;
|
2018-07-30 19:24:48 +00:00
|
|
|
|
|
|
|
// If this function was instantiated from a member function of a
|
2009-09-11 20:15:17 +00:00
|
|
|
// class template, check whether that member function was defined out-of-line.
|
|
|
|
if (FunctionDecl *FD = getInstantiatedFromMemberFunction()) {
|
|
|
|
const FunctionDecl *Definition;
|
2010-07-07 11:31:19 +00:00
|
|
|
if (FD->hasBody(Definition))
|
2009-09-11 20:15:17 +00:00
|
|
|
return Definition->isOutOfLine();
|
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2009-09-11 20:15:17 +00:00
|
|
|
// 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;
|
2010-07-07 11:31:19 +00:00
|
|
|
if (FunTmpl->getTemplatedDecl()->hasBody(Definition))
|
2009-09-11 20:15:17 +00:00
|
|
|
return Definition->isOutOfLine();
|
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2009-09-11 20:15:17 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-03-08 16:41:52 +00:00
|
|
|
SourceRange FunctionDecl::getSourceRange() const {
|
|
|
|
return SourceRange(getOuterLocStart(), EndRangeLoc);
|
|
|
|
}
|
|
|
|
|
2012-01-18 02:45:01 +00:00
|
|
|
unsigned FunctionDecl::getMemoryFunctionKind() const {
|
2012-01-13 21:52:01 +00:00
|
|
|
IdentifierInfo *FnInfo = getIdentifier();
|
|
|
|
|
|
|
|
if (!FnInfo)
|
2012-01-17 00:37:07 +00:00
|
|
|
return 0;
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2012-01-13 21:52:01 +00:00
|
|
|
// Builtin handling.
|
|
|
|
switch (getBuiltinID()) {
|
|
|
|
case Builtin::BI__builtin_memset:
|
|
|
|
case Builtin::BI__builtin___memset_chk:
|
|
|
|
case Builtin::BImemset:
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BImemset;
|
2012-01-13 21:52:01 +00:00
|
|
|
|
|
|
|
case Builtin::BI__builtin_memcpy:
|
|
|
|
case Builtin::BI__builtin___memcpy_chk:
|
|
|
|
case Builtin::BImemcpy:
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BImemcpy;
|
2012-01-13 21:52:01 +00:00
|
|
|
|
2019-12-11 20:30:10 +00:00
|
|
|
case Builtin::BI__builtin_mempcpy:
|
|
|
|
case Builtin::BI__builtin___mempcpy_chk:
|
|
|
|
case Builtin::BImempcpy:
|
|
|
|
return Builtin::BImempcpy;
|
|
|
|
|
2012-01-13 21:52:01 +00:00
|
|
|
case Builtin::BI__builtin_memmove:
|
|
|
|
case Builtin::BI__builtin___memmove_chk:
|
|
|
|
case Builtin::BImemmove:
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BImemmove;
|
2012-01-13 21:52:01 +00:00
|
|
|
|
|
|
|
case Builtin::BIstrlcpy:
|
2014-09-12 18:44:36 +00:00
|
|
|
case Builtin::BI__builtin___strlcpy_chk:
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BIstrlcpy;
|
2014-09-12 18:44:36 +00:00
|
|
|
|
2012-01-13 21:52:01 +00:00
|
|
|
case Builtin::BIstrlcat:
|
2014-09-12 18:44:36 +00:00
|
|
|
case Builtin::BI__builtin___strlcat_chk:
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BIstrlcat;
|
2012-01-13 21:52:01 +00:00
|
|
|
|
|
|
|
case Builtin::BI__builtin_memcmp:
|
2012-01-17 00:37:07 +00:00
|
|
|
case Builtin::BImemcmp:
|
|
|
|
return Builtin::BImemcmp;
|
2012-01-13 21:52:01 +00:00
|
|
|
|
2019-02-14 12:00:34 +00:00
|
|
|
case Builtin::BI__builtin_bcmp:
|
|
|
|
case Builtin::BIbcmp:
|
|
|
|
return Builtin::BIbcmp;
|
|
|
|
|
2012-01-13 21:52:01 +00:00
|
|
|
case Builtin::BI__builtin_strncpy:
|
|
|
|
case Builtin::BI__builtin___strncpy_chk:
|
|
|
|
case Builtin::BIstrncpy:
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BIstrncpy;
|
2012-01-13 21:52:01 +00:00
|
|
|
|
|
|
|
case Builtin::BI__builtin_strncmp:
|
2012-01-17 00:37:07 +00:00
|
|
|
case Builtin::BIstrncmp:
|
|
|
|
return Builtin::BIstrncmp;
|
2012-01-13 21:52:01 +00:00
|
|
|
|
|
|
|
case Builtin::BI__builtin_strncasecmp:
|
2012-01-17 00:37:07 +00:00
|
|
|
case Builtin::BIstrncasecmp:
|
|
|
|
return Builtin::BIstrncasecmp;
|
2012-01-13 21:52:01 +00:00
|
|
|
|
|
|
|
case Builtin::BI__builtin_strncat:
|
2012-02-01 19:08:57 +00:00
|
|
|
case Builtin::BI__builtin___strncat_chk:
|
2012-01-13 21:52:01 +00:00
|
|
|
case Builtin::BIstrncat:
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BIstrncat;
|
2012-01-13 21:52:01 +00:00
|
|
|
|
|
|
|
case Builtin::BI__builtin_strndup:
|
|
|
|
case Builtin::BIstrndup:
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BIstrndup;
|
2012-01-13 21:52:01 +00:00
|
|
|
|
2012-02-01 19:08:57 +00:00
|
|
|
case Builtin::BI__builtin_strlen:
|
|
|
|
case Builtin::BIstrlen:
|
|
|
|
return Builtin::BIstrlen;
|
|
|
|
|
2016-08-10 18:34:47 +00:00
|
|
|
case Builtin::BI__builtin_bzero:
|
|
|
|
case Builtin::BIbzero:
|
|
|
|
return Builtin::BIbzero;
|
|
|
|
|
2023-09-24 14:58:14 +00:00
|
|
|
case Builtin::BI__builtin_bcopy:
|
|
|
|
case Builtin::BIbcopy:
|
|
|
|
return Builtin::BIbcopy;
|
|
|
|
|
2020-10-28 23:16:17 +00:00
|
|
|
case Builtin::BIfree:
|
|
|
|
return Builtin::BIfree;
|
|
|
|
|
2012-01-13 21:52:01 +00:00
|
|
|
default:
|
2013-02-14 01:47:04 +00:00
|
|
|
if (isExternC()) {
|
2012-01-13 21:52:01 +00:00
|
|
|
if (FnInfo->isStr("memset"))
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BImemset;
|
2021-01-25 10:09:56 +00:00
|
|
|
if (FnInfo->isStr("memcpy"))
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BImemcpy;
|
2021-01-25 10:09:56 +00:00
|
|
|
if (FnInfo->isStr("mempcpy"))
|
2019-12-11 20:30:10 +00:00
|
|
|
return Builtin::BImempcpy;
|
2021-01-25 10:09:56 +00:00
|
|
|
if (FnInfo->isStr("memmove"))
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BImemmove;
|
2021-01-25 10:09:56 +00:00
|
|
|
if (FnInfo->isStr("memcmp"))
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BImemcmp;
|
2021-01-25 10:09:56 +00:00
|
|
|
if (FnInfo->isStr("bcmp"))
|
2019-02-14 12:00:34 +00:00
|
|
|
return Builtin::BIbcmp;
|
2021-01-25 10:09:56 +00:00
|
|
|
if (FnInfo->isStr("strncpy"))
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BIstrncpy;
|
2021-01-25 10:09:56 +00:00
|
|
|
if (FnInfo->isStr("strncmp"))
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BIstrncmp;
|
2021-01-25 10:09:56 +00:00
|
|
|
if (FnInfo->isStr("strncasecmp"))
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BIstrncasecmp;
|
2021-01-25 10:09:56 +00:00
|
|
|
if (FnInfo->isStr("strncat"))
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BIstrncat;
|
2021-01-25 10:09:56 +00:00
|
|
|
if (FnInfo->isStr("strndup"))
|
2012-01-17 00:37:07 +00:00
|
|
|
return Builtin::BIstrndup;
|
2021-01-25 10:09:56 +00:00
|
|
|
if (FnInfo->isStr("strlen"))
|
2012-02-01 19:08:57 +00:00
|
|
|
return Builtin::BIstrlen;
|
2021-01-25 10:09:56 +00:00
|
|
|
if (FnInfo->isStr("bzero"))
|
2016-08-10 18:34:47 +00:00
|
|
|
return Builtin::BIbzero;
|
2023-09-24 14:58:14 +00:00
|
|
|
if (FnInfo->isStr("bcopy"))
|
|
|
|
return Builtin::BIbcopy;
|
2020-10-28 23:16:17 +00:00
|
|
|
} else if (isInStdNamespace()) {
|
|
|
|
if (FnInfo->isStr("free"))
|
|
|
|
return Builtin::BIfree;
|
2012-01-13 21:52:01 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2012-01-17 00:37:07 +00:00
|
|
|
return 0;
|
2012-01-13 21:52:01 +00:00
|
|
|
}
|
|
|
|
|
2018-07-10 01:40:50 +00:00
|
|
|
unsigned FunctionDecl::getODRHash() const {
|
2018-08-01 21:02:40 +00:00
|
|
|
assert(hasODRHash());
|
2018-07-10 01:40:50 +00:00
|
|
|
return ODRHash;
|
|
|
|
}
|
|
|
|
|
2017-12-23 00:41:01 +00:00
|
|
|
unsigned FunctionDecl::getODRHash() {
|
2018-08-01 21:02:40 +00:00
|
|
|
if (hasODRHash())
|
2017-12-23 00:41:01 +00:00
|
|
|
return ODRHash;
|
|
|
|
|
2018-02-22 05:50:29 +00:00
|
|
|
if (auto *FT = getInstantiatedFromMemberFunction()) {
|
2018-08-01 21:02:40 +00:00
|
|
|
setHasODRHash(true);
|
2018-02-22 05:50:29 +00:00
|
|
|
ODRHash = FT->getODRHash();
|
|
|
|
return ODRHash;
|
|
|
|
}
|
|
|
|
|
2017-12-23 00:41:01 +00:00
|
|
|
class ODRHash Hash;
|
|
|
|
Hash.AddFunctionDecl(this);
|
2018-08-01 21:02:40 +00:00
|
|
|
setHasODRHash(true);
|
2017-12-23 00:41:01 +00:00
|
|
|
ODRHash = Hash.CalculateHash();
|
|
|
|
return ODRHash;
|
|
|
|
}
|
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// FieldDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-01-12 09:06:06 +00:00
|
|
|
FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC,
|
2011-03-08 08:55:46 +00:00
|
|
|
SourceLocation StartLoc, SourceLocation IdLoc,
|
|
|
|
IdentifierInfo *Id, QualType T,
|
2011-06-11 17:19:42 +00:00
|
|
|
TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
|
2012-06-10 03:12:00 +00:00
|
|
|
InClassInitStyle InitStyle) {
|
2013-11-22 09:01:48 +00:00
|
|
|
return new (C, DC) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo,
|
|
|
|
BW, Mutable, InitStyle);
|
2010-01-26 22:01:41 +00:00
|
|
|
}
|
|
|
|
|
2012-01-05 21:55:30 +00:00
|
|
|
FieldDecl *FieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2014-05-12 05:36:57 +00:00
|
|
|
return new (C, ID) FieldDecl(Field, nullptr, SourceLocation(),
|
|
|
|
SourceLocation(), nullptr, QualType(), nullptr,
|
|
|
|
nullptr, false, ICIS_NoInit);
|
2012-01-05 21:55:30 +00:00
|
|
|
}
|
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
bool FieldDecl::isAnonymousStructOrUnion() const {
|
|
|
|
if (!isImplicit() || getDeclName())
|
|
|
|
return false;
|
|
|
|
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *Record = getType()->getAs<RecordType>())
|
2010-01-26 22:01:41 +00:00
|
|
|
return Record->getDecl()->isAnonymousStructOrUnion();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-04-05 21:28:57 +00:00
|
|
|
Expr *FieldDecl::getInClassInitializer() const {
|
|
|
|
if (!hasInClassInitializer())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
LazyDeclStmtPtr InitPtr = BitField ? InitAndBitWidth->Init : Init;
|
2023-09-13 12:53:27 +00:00
|
|
|
return cast_if_present<Expr>(
|
2023-04-05 21:28:57 +00:00
|
|
|
InitPtr.isOffset() ? InitPtr.get(getASTContext().getExternalSource())
|
|
|
|
: InitPtr.get(nullptr));
|
|
|
|
}
|
|
|
|
|
|
|
|
void FieldDecl::setInClassInitializer(Expr *NewInit) {
|
|
|
|
setLazyInClassInitializer(LazyDeclStmtPtr(NewInit));
|
|
|
|
}
|
|
|
|
|
|
|
|
void FieldDecl::setLazyInClassInitializer(LazyDeclStmtPtr NewInit) {
|
|
|
|
assert(hasInClassInitializer() && !getInClassInitializer());
|
|
|
|
if (BitField)
|
|
|
|
InitAndBitWidth->Init = NewInit;
|
|
|
|
else
|
|
|
|
Init = NewInit;
|
|
|
|
}
|
|
|
|
|
2011-10-10 18:28:20 +00:00
|
|
|
unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
|
|
|
|
assert(isBitField() && "not a bitfield");
|
2017-08-28 00:28:14 +00:00
|
|
|
return getBitWidth()->EvaluateKnownConstInt(Ctx).getZExtValue();
|
2011-10-10 18:28:20 +00:00
|
|
|
}
|
|
|
|
|
2018-04-02 18:29:43 +00:00
|
|
|
bool FieldDecl::isZeroLengthBitField(const ASTContext &Ctx) const {
|
|
|
|
return isUnnamedBitfield() && !getBitWidth()->isValueDependent() &&
|
|
|
|
getBitWidthValue(Ctx) == 0;
|
|
|
|
}
|
|
|
|
|
2019-06-20 20:44:45 +00:00
|
|
|
bool FieldDecl::isZeroSize(const ASTContext &Ctx) const {
|
|
|
|
if (isZeroLengthBitField(Ctx))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// C++2a [intro.object]p7:
|
|
|
|
// An object has nonzero size if it
|
|
|
|
// -- is not a potentially-overlapping subobject, or
|
|
|
|
if (!hasAttr<NoUniqueAddressAttr>())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// -- is not of class type, or
|
|
|
|
const auto *RT = getType()->getAs<RecordType>();
|
|
|
|
if (!RT)
|
|
|
|
return false;
|
|
|
|
const RecordDecl *RD = RT->getDecl()->getDefinition();
|
|
|
|
if (!RD) {
|
|
|
|
assert(isInvalidDecl() && "valid field has incomplete type");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -- [has] virtual member functions or virtual base classes, or
|
|
|
|
// -- has subobjects of nonzero size or bit-fields of nonzero length
|
|
|
|
const auto *CXXRD = cast<CXXRecordDecl>(RD);
|
|
|
|
if (!CXXRD->isEmpty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Otherwise, [...] the circumstances under which the object has zero size
|
|
|
|
// are implementation-defined.
|
2023-09-28 21:29:32 +00:00
|
|
|
if (!Ctx.getTargetInfo().getCXXABI().isMicrosoft())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// MS ABI: has nonzero size if it is a class type with class type fields,
|
|
|
|
// whether or not they have nonzero size
|
|
|
|
return !llvm::any_of(CXXRD->fields(), [](const FieldDecl *Field) {
|
|
|
|
return Field->getType()->getAs<RecordType>();
|
|
|
|
});
|
2019-06-20 20:44:45 +00:00
|
|
|
}
|
|
|
|
|
2023-01-13 23:38:10 +00:00
|
|
|
bool FieldDecl::isPotentiallyOverlapping() const {
|
|
|
|
return hasAttr<NoUniqueAddressAttr>() && getType()->getAsCXXRecordDecl();
|
|
|
|
}
|
|
|
|
|
2011-01-20 07:57:12 +00:00
|
|
|
unsigned FieldDecl::getFieldIndex() const {
|
2013-10-07 08:02:11 +00:00
|
|
|
const FieldDecl *Canonical = getCanonicalDecl();
|
|
|
|
if (Canonical != this)
|
|
|
|
return Canonical->getFieldIndex();
|
|
|
|
|
2011-01-20 07:57:12 +00:00
|
|
|
if (CachedFieldIndex) return CachedFieldIndex - 1;
|
|
|
|
|
2011-11-10 06:34:14 +00:00
|
|
|
unsigned Index = 0;
|
2017-11-15 01:33:46 +00:00
|
|
|
const RecordDecl *RD = getParent()->getDefinition();
|
|
|
|
assert(RD && "requested index for field of struct with no definition");
|
2011-11-10 06:34:14 +00:00
|
|
|
|
2014-08-21 16:06:57 +00:00
|
|
|
for (auto *Field : RD->fields()) {
|
|
|
|
Field->getCanonicalDecl()->CachedFieldIndex = Index + 1;
|
2023-04-05 21:28:57 +00:00
|
|
|
assert(Field->getCanonicalDecl()->CachedFieldIndex == Index + 1 &&
|
|
|
|
"overflow in field numbering");
|
2014-08-21 16:06:57 +00:00
|
|
|
++Index;
|
|
|
|
}
|
2011-01-20 07:57:12 +00:00
|
|
|
|
2011-11-10 06:34:14 +00:00
|
|
|
assert(CachedFieldIndex && "failed to find field in parent");
|
|
|
|
return CachedFieldIndex - 1;
|
2011-01-20 07:57:12 +00:00
|
|
|
}
|
|
|
|
|
2011-03-08 11:07:11 +00:00
|
|
|
SourceRange FieldDecl::getSourceRange() const {
|
2017-08-28 00:28:14 +00:00
|
|
|
const Expr *FinalExpr = getInClassInitializer();
|
|
|
|
if (!FinalExpr)
|
|
|
|
FinalExpr = getBitWidth();
|
|
|
|
if (FinalExpr)
|
2018-08-09 21:09:38 +00:00
|
|
|
return SourceRange(getInnerLocStart(), FinalExpr->getEndLoc());
|
2017-08-28 00:28:14 +00:00
|
|
|
return DeclaratorDecl::getSourceRange();
|
2014-08-28 04:28:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) {
|
2014-10-31 17:18:09 +00:00
|
|
|
assert((getParent()->isLambda() || getParent()->isCapturedRecord()) &&
|
2014-10-29 12:21:55 +00:00
|
|
|
"capturing type in non-lambda or captured record.");
|
2023-04-05 21:28:57 +00:00
|
|
|
assert(StorageKind == ISK_NoInit && !BitField &&
|
|
|
|
"bit-field or field with default member initializer cannot capture "
|
|
|
|
"VLA type");
|
|
|
|
StorageKind = ISK_CapturedVLAType;
|
|
|
|
CapturedVLAType = VLAType;
|
2014-08-28 04:28:19 +00:00
|
|
|
}
|
|
|
|
|
2023-08-24 13:27:02 +00:00
|
|
|
void FieldDecl::printName(raw_ostream &OS, const PrintingPolicy &Policy) const {
|
|
|
|
// Print unnamed members using name of their type.
|
|
|
|
if (isAnonymousStructOrUnion()) {
|
|
|
|
this->getType().print(OS, Policy);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Otherwise, do the normal printing.
|
|
|
|
DeclaratorDecl::printName(OS, Policy);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
//===----------------------------------------------------------------------===//
|
2009-01-07 00:43:41 +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
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-08-01 20:48:16 +00:00
|
|
|
TagDecl::TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl,
|
|
|
|
SourceLocation StartL)
|
|
|
|
: TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), redeclarable_base(C),
|
|
|
|
TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) {
|
2023-11-03 17:45:39 +00:00
|
|
|
assert((DK != Enum || TK == TagTypeKind::Enum) &&
|
|
|
|
"EnumDecl not matched with TagTypeKind::Enum");
|
2018-08-01 20:48:16 +00:00
|
|
|
setPreviousDecl(PrevDecl);
|
|
|
|
setTagKind(TK);
|
|
|
|
setCompleteDefinition(false);
|
|
|
|
setBeingDefined(false);
|
|
|
|
setEmbeddedInDeclarator(false);
|
|
|
|
setFreeStanding(false);
|
|
|
|
setCompleteDefinitionRequired(false);
|
2022-02-01 23:03:59 +00:00
|
|
|
TagDeclBits.IsThisDeclarationADemotedDefinition = false;
|
2018-08-01 20:48:16 +00:00
|
|
|
}
|
|
|
|
|
2010-07-06 18:42:40 +00:00
|
|
|
SourceLocation TagDecl::getOuterLocStart() const {
|
|
|
|
return getTemplateOrInnerLocStart(this);
|
|
|
|
}
|
|
|
|
|
2009-07-14 03:17:17 +00:00
|
|
|
SourceRange TagDecl::getSourceRange() const {
|
2016-07-15 18:11:33 +00:00
|
|
|
SourceLocation RBraceLoc = BraceRange.getEnd();
|
2009-07-14 03:17:17 +00:00
|
|
|
SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation();
|
2010-07-06 18:42:40 +00:00
|
|
|
return SourceRange(getOuterLocStart(), E);
|
2009-07-14 03:17:17 +00:00
|
|
|
}
|
|
|
|
|
2013-10-17 15:37:26 +00:00
|
|
|
TagDecl *TagDecl::getCanonicalDecl() { return getFirstDecl(); }
|
2009-07-18 00:34:07 +00:00
|
|
|
|
2013-03-12 21:06:00 +00:00
|
|
|
void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) {
|
2015-08-31 18:48:39 +00:00
|
|
|
TypedefNameDeclOrQualifier = TDD;
|
2014-04-23 22:03:04 +00:00
|
|
|
if (const Type *T = getTypeForDecl()) {
|
|
|
|
(void)T;
|
2014-04-23 18:20:42 +00:00
|
|
|
assert(T->isLinkageValid());
|
2014-04-23 22:03:04 +00:00
|
|
|
}
|
2013-03-14 03:07:35 +00:00
|
|
|
assert(isLinkageValid());
|
2010-05-19 18:39:18 +00:00
|
|
|
}
|
|
|
|
|
2009-01-17 00:42:38 +00:00
|
|
|
void TagDecl::startDefinition() {
|
2018-08-01 20:48:16 +00:00
|
|
|
setBeingDefined(true);
|
2010-02-04 22:26:26 +00:00
|
|
|
|
2015-11-09 17:53:06 +00:00
|
|
|
if (auto *D = dyn_cast<CXXRecordDecl>(this)) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-16 23:01:30 +00:00
|
|
|
struct CXXRecordDecl::DefinitionData *Data =
|
2010-02-04 22:26:26 +00:00
|
|
|
new (getASTContext()) struct CXXRecordDecl::DefinitionData(D);
|
2022-09-04 06:27:27 +00:00
|
|
|
for (auto *I : redecls())
|
2014-05-22 23:19:02 +00:00
|
|
|
cast<CXXRecordDecl>(I)->DefinitionData = Data;
|
2010-02-04 22:26:26 +00:00
|
|
|
}
|
2009-01-17 00:42:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TagDecl::completeDefinition() {
|
2010-02-05 01:33:36 +00:00
|
|
|
assert((!isa<CXXRecordDecl>(this) ||
|
|
|
|
cast<CXXRecordDecl>(this)->hasDefinition()) &&
|
|
|
|
"definition completed but not started");
|
|
|
|
|
2018-08-01 20:48:16 +00:00
|
|
|
setCompleteDefinition(true);
|
|
|
|
setBeingDefined(false);
|
2010-10-24 17:26:50 +00:00
|
|
|
|
|
|
|
if (ASTMutationListener *L = getASTMutationListener())
|
|
|
|
L->CompletedTagDefinition(this);
|
2009-01-17 00:42:38 +00:00
|
|
|
}
|
|
|
|
|
2011-10-07 06:10:15 +00:00
|
|
|
TagDecl *TagDecl::getDefinition() const {
|
|
|
|
if (isCompleteDefinition())
|
2009-07-29 23:36:44 +00:00
|
|
|
return const_cast<TagDecl *>(this);
|
Ensure that type definitions present in just-loaded modules are
visible.
The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,
class X;
X *x;
and then import a module that includes a definition of X:
import XDef;
We will then fail when attempting to access a member of X, e.g.,
x->method()
because the AST reader did not know to look for a default of a class
named X within the new module.
This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.
In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,
// module 1
namespace N { struct X; }
// module 2
namespace N { struct X { /* ... */ }; }
One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.
llvm-svn: 174794
2013-02-09 01:35:03 +00:00
|
|
|
|
|
|
|
// If it's possible for us to have an out-of-date definition, check now.
|
2018-08-01 20:48:16 +00:00
|
|
|
if (mayHaveOutOfDateDef()) {
|
Ensure that type definitions present in just-loaded modules are
visible.
The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,
class X;
X *x;
and then import a module that includes a definition of X:
import XDef;
We will then fail when attempting to access a member of X, e.g.,
x->method()
because the AST reader did not know to look for a default of a class
named X within the new module.
This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.
In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,
// module 1
namespace N { struct X; }
// module 2
namespace N { struct X { /* ... */ }; }
One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.
llvm-svn: 174794
2013-02-09 01:35:03 +00:00
|
|
|
if (IdentifierInfo *II = getIdentifier()) {
|
|
|
|
if (II->isOutOfDate()) {
|
|
|
|
updateOutOfDate(*II);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(this))
|
2010-10-19 21:54:32 +00:00
|
|
|
return CXXRD->getDefinition();
|
2009-09-09 15:08:12 +00:00
|
|
|
|
2022-09-04 06:27:27 +00:00
|
|
|
for (auto *R : redecls())
|
2011-10-07 06:10:15 +00:00
|
|
|
if (R->isCompleteDefinition())
|
2014-03-06 23:45:36 +00:00
|
|
|
return R;
|
2009-09-09 15:08:12 +00:00
|
|
|
|
2014-05-12 05:36:57 +00:00
|
|
|
return nullptr;
|
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
|
|
|
}
|
|
|
|
|
2011-02-25 02:25:35 +00:00
|
|
|
void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
|
|
|
|
if (QualifierLoc) {
|
2010-03-15 10:12:16 +00:00
|
|
|
// Make sure the extended qualifier info is allocated.
|
|
|
|
if (!hasExtInfo())
|
2015-08-31 18:48:39 +00:00
|
|
|
TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo;
|
2010-03-15 10:12:16 +00:00
|
|
|
// Set qualifier info.
|
2011-02-25 02:25:35 +00:00
|
|
|
getExtInfo()->QualifierLoc = QualifierLoc;
|
2011-08-17 23:08:45 +00:00
|
|
|
} else {
|
2010-03-15 10:12:16 +00:00
|
|
|
// Here Qualifier == 0, i.e., we are removing the qualifier (if any).
|
|
|
|
if (hasExtInfo()) {
|
2011-03-18 15:16:37 +00:00
|
|
|
if (getExtInfo()->NumTemplParamLists == 0) {
|
|
|
|
getASTContext().Deallocate(getExtInfo());
|
2015-08-31 18:48:39 +00:00
|
|
|
TypedefNameDeclOrQualifier = (TypedefNameDecl *)nullptr;
|
2011-03-18 15:16:37 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
getExtInfo()->QualifierLoc = QualifierLoc;
|
2010-03-15 10:12:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-14 12:17:16 +00:00
|
|
|
void TagDecl::printName(raw_ostream &OS, const PrintingPolicy &Policy) const {
|
|
|
|
DeclarationName Name = getDeclName();
|
|
|
|
// If the name is supposed to have an identifier but does not have one, then
|
|
|
|
// the tag is anonymous and we should print it differently.
|
|
|
|
if (Name.isIdentifier() && !Name.getAsIdentifierInfo()) {
|
|
|
|
// If the caller wanted to print a qualified name, they've already printed
|
|
|
|
// the scope. And if the caller doesn't want that, the scope information
|
|
|
|
// is already printed as part of the type.
|
|
|
|
PrintingPolicy Copy(Policy);
|
|
|
|
Copy.SuppressScope = true;
|
|
|
|
getASTContext().getTagDeclType(this).print(OS, Copy);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Otherwise, do the normal printing.
|
|
|
|
Name.print(OS, Policy);
|
|
|
|
}
|
|
|
|
|
2015-08-05 09:40:49 +00:00
|
|
|
void TagDecl::setTemplateParameterListsInfo(
|
|
|
|
ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
|
|
|
|
assert(!TPLists.empty());
|
2011-03-18 15:16:37 +00:00
|
|
|
// Make sure the extended decl info is allocated.
|
|
|
|
if (!hasExtInfo())
|
|
|
|
// Allocate external info struct.
|
2015-08-31 18:48:39 +00:00
|
|
|
TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo;
|
2011-03-18 15:16:37 +00:00
|
|
|
// Set the template parameter lists info.
|
2015-08-05 09:40:49 +00:00
|
|
|
getExtInfo()->setTemplateParameterListsInfo(Context, TPLists);
|
2011-03-18 15:16:37 +00:00
|
|
|
}
|
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// EnumDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-08-01 20:48:16 +00:00
|
|
|
EnumDecl::EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl,
|
|
|
|
bool Scoped, bool ScopedUsingClassTag, bool Fixed)
|
2023-11-03 17:45:39 +00:00
|
|
|
: TagDecl(Enum, TagTypeKind::Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc) {
|
2018-08-01 20:48:16 +00:00
|
|
|
assert(Scoped || !ScopedUsingClassTag);
|
|
|
|
IntegerType = nullptr;
|
|
|
|
setNumPositiveBits(0);
|
|
|
|
setNumNegativeBits(0);
|
|
|
|
setScoped(Scoped);
|
|
|
|
setScopedUsingClassTag(ScopedUsingClassTag);
|
|
|
|
setFixed(Fixed);
|
|
|
|
setHasODRHash(false);
|
|
|
|
ODRHash = 0;
|
|
|
|
}
|
|
|
|
|
2017-11-13 23:01:27 +00:00
|
|
|
void EnumDecl::anchor() {}
|
2011-12-20 02:48:34 +00:00
|
|
|
|
2011-03-09 14:09:51 +00:00
|
|
|
EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation StartLoc, SourceLocation IdLoc,
|
|
|
|
IdentifierInfo *Id,
|
2010-12-03 18:54:17 +00:00
|
|
|
EnumDecl *PrevDecl, bool IsScoped,
|
|
|
|
bool IsScopedUsingClassTag, bool IsFixed) {
|
2015-11-09 17:53:06 +00:00
|
|
|
auto *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl,
|
|
|
|
IsScoped, IsScopedUsingClassTag, IsFixed);
|
2018-08-01 20:48:16 +00:00
|
|
|
Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
|
2010-01-26 22:01:41 +00:00
|
|
|
C.getTypeDeclType(Enum, PrevDecl);
|
|
|
|
return Enum;
|
|
|
|
}
|
|
|
|
|
2012-01-05 21:55:30 +00:00
|
|
|
EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-16 23:01:30 +00:00
|
|
|
EnumDecl *Enum =
|
|
|
|
new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(),
|
|
|
|
nullptr, nullptr, false, false, false);
|
2018-08-01 20:48:16 +00:00
|
|
|
Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
|
Ensure that type definitions present in just-loaded modules are
visible.
The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,
class X;
X *x;
and then import a module that includes a definition of X:
import XDef;
We will then fail when attempting to access a member of X, e.g.,
x->method()
because the AST reader did not know to look for a default of a class
named X within the new module.
This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.
In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,
// module 1
namespace N { struct X; }
// module 2
namespace N { struct X { /* ... */ }; }
One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.
llvm-svn: 174794
2013-02-09 01:35:03 +00:00
|
|
|
return Enum;
|
2010-07-02 11:54:55 +00:00
|
|
|
}
|
|
|
|
|
2014-01-06 11:31:18 +00:00
|
|
|
SourceRange EnumDecl::getIntegerTypeRange() const {
|
|
|
|
if (const TypeSourceInfo *TI = getIntegerTypeSourceInfo())
|
|
|
|
return TI->getTypeLoc().getSourceRange();
|
|
|
|
return SourceRange();
|
|
|
|
}
|
|
|
|
|
2010-02-11 01:19:42 +00:00
|
|
|
void EnumDecl::completeDefinition(QualType NewType,
|
2010-05-06 08:49:23 +00:00
|
|
|
QualType NewPromotionType,
|
|
|
|
unsigned NumPositiveBits,
|
|
|
|
unsigned NumNegativeBits) {
|
2011-10-07 06:10:15 +00:00
|
|
|
assert(!isCompleteDefinition() && "Cannot redefine enums!");
|
2010-10-08 23:50:27 +00:00
|
|
|
if (!IntegerType)
|
|
|
|
IntegerType = NewType.getTypePtr();
|
2010-01-26 22:01:41 +00:00
|
|
|
PromotionType = NewPromotionType;
|
2010-05-06 08:49:23 +00:00
|
|
|
setNumPositiveBits(NumPositiveBits);
|
|
|
|
setNumNegativeBits(NumNegativeBits);
|
2010-01-26 22:01:41 +00:00
|
|
|
TagDecl::completeDefinition();
|
|
|
|
}
|
|
|
|
|
2017-03-21 02:23:00 +00:00
|
|
|
bool EnumDecl::isClosed() const {
|
|
|
|
if (const auto *A = getAttr<EnumExtensibilityAttr>())
|
|
|
|
return A->getExtensibility() == EnumExtensibilityAttr::Closed;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool EnumDecl::isClosedFlag() const {
|
|
|
|
return isClosed() && hasAttr<FlagEnumAttr>();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool EnumDecl::isClosedNonFlag() const {
|
|
|
|
return isClosed() && !hasAttr<FlagEnumAttr>();
|
|
|
|
}
|
|
|
|
|
2012-03-23 03:33:32 +00:00
|
|
|
TemplateSpecializationKind EnumDecl::getTemplateSpecializationKind() const {
|
|
|
|
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
|
|
|
|
return MSI->getTemplateSpecializationKind();
|
|
|
|
|
|
|
|
return TSK_Undeclared;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EnumDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
|
|
|
|
SourceLocation PointOfInstantiation) {
|
|
|
|
MemberSpecializationInfo *MSI = getMemberSpecializationInfo();
|
|
|
|
assert(MSI && "Not an instantiated member enumeration?");
|
|
|
|
MSI->setTemplateSpecializationKind(TSK);
|
|
|
|
if (TSK != TSK_ExplicitSpecialization &&
|
|
|
|
PointOfInstantiation.isValid() &&
|
|
|
|
MSI->getPointOfInstantiation().isInvalid())
|
|
|
|
MSI->setPointOfInstantiation(PointOfInstantiation);
|
|
|
|
}
|
|
|
|
|
2016-05-05 00:56:12 +00:00
|
|
|
EnumDecl *EnumDecl::getTemplateInstantiationPattern() const {
|
|
|
|
if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
|
|
|
|
if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) {
|
|
|
|
EnumDecl *ED = getInstantiatedFromMemberEnum();
|
|
|
|
while (auto *NewED = ED->getInstantiatedFromMemberEnum())
|
|
|
|
ED = NewED;
|
2017-04-21 01:15:13 +00:00
|
|
|
return getDefinitionOrSelf(ED);
|
2016-05-05 00:56:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(!isTemplateInstantiation(getTemplateSpecializationKind()) &&
|
|
|
|
"couldn't find pattern for enum instantiation");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2012-03-14 23:13:10 +00:00
|
|
|
EnumDecl *EnumDecl::getInstantiatedFromMemberEnum() const {
|
|
|
|
if (SpecializationInfo)
|
|
|
|
return cast<EnumDecl>(SpecializationInfo->getInstantiatedFrom());
|
|
|
|
|
2014-05-12 05:36:57 +00:00
|
|
|
return nullptr;
|
2012-03-14 23:13:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
|
|
|
|
TemplateSpecializationKind TSK) {
|
|
|
|
assert(!SpecializationInfo && "Member enum is already a specialization");
|
|
|
|
SpecializationInfo = new (C) MemberSpecializationInfo(ED, TSK);
|
|
|
|
}
|
|
|
|
|
2018-07-25 22:52:05 +00:00
|
|
|
unsigned EnumDecl::getODRHash() {
|
2018-08-01 20:48:16 +00:00
|
|
|
if (hasODRHash())
|
2018-07-25 22:52:05 +00:00
|
|
|
return ODRHash;
|
|
|
|
|
|
|
|
class ODRHash Hash;
|
|
|
|
Hash.AddEnumDecl(this);
|
2018-08-01 20:48:16 +00:00
|
|
|
setHasODRHash(true);
|
2018-07-25 22:52:05 +00:00
|
|
|
ODRHash = Hash.CalculateHash();
|
|
|
|
return ODRHash;
|
|
|
|
}
|
|
|
|
|
2021-10-06 18:25:26 +00:00
|
|
|
SourceRange EnumDecl::getSourceRange() const {
|
|
|
|
auto Res = TagDecl::getSourceRange();
|
|
|
|
// Set end-point to enum-base, e.g. enum foo : ^bar
|
|
|
|
if (auto *TSI = getIntegerTypeSourceInfo()) {
|
|
|
|
// TagDecl doesn't know about the enum base.
|
|
|
|
if (!getBraceRange().getEnd().isValid())
|
|
|
|
Res.setEnd(TSI->getTypeLoc().getEndLoc());
|
|
|
|
}
|
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
|
2022-07-28 22:26:15 +00:00
|
|
|
void EnumDecl::getValueRange(llvm::APInt &Max, llvm::APInt &Min) const {
|
|
|
|
unsigned Bitwidth = getASTContext().getIntWidth(getIntegerType());
|
|
|
|
unsigned NumNegativeBits = getNumNegativeBits();
|
|
|
|
unsigned NumPositiveBits = getNumPositiveBits();
|
|
|
|
|
|
|
|
if (NumNegativeBits) {
|
|
|
|
unsigned NumBits = std::max(NumNegativeBits, NumPositiveBits + 1);
|
|
|
|
Max = llvm::APInt(Bitwidth, 1) << (NumBits - 1);
|
|
|
|
Min = -Max;
|
|
|
|
} else {
|
|
|
|
Max = llvm::APInt(Bitwidth, 1) << NumPositiveBits;
|
|
|
|
Min = llvm::APInt::getZero(Bitwidth);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-31 00:36:02 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// RecordDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
2007-01-25 04:52:46 +00:00
|
|
|
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-16 23:01:30 +00:00
|
|
|
RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C,
|
|
|
|
DeclContext *DC, SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc, IdentifierInfo *Id,
|
|
|
|
RecordDecl *PrevDecl)
|
2018-08-01 20:48:16 +00:00
|
|
|
: TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc) {
|
|
|
|
assert(classof(static_cast<Decl *>(this)) && "Invalid Kind!");
|
|
|
|
setHasFlexibleArrayMember(false);
|
|
|
|
setAnonymousStructOrUnion(false);
|
|
|
|
setHasObjectMember(false);
|
|
|
|
setHasVolatileMember(false);
|
|
|
|
setHasLoadedFieldsFromExternalStorage(false);
|
|
|
|
setNonTrivialToPrimitiveDefaultInitialize(false);
|
|
|
|
setNonTrivialToPrimitiveCopy(false);
|
|
|
|
setNonTrivialToPrimitiveDestroy(false);
|
2019-09-07 00:34:43 +00:00
|
|
|
setHasNonTrivialToPrimitiveDefaultInitializeCUnion(false);
|
|
|
|
setHasNonTrivialToPrimitiveDestructCUnion(false);
|
|
|
|
setHasNonTrivialToPrimitiveCopyCUnion(false);
|
2018-08-01 20:48:16 +00:00
|
|
|
setParamDestroyedInCallee(false);
|
2023-11-01 16:38:28 +00:00
|
|
|
setArgPassingRestrictions(RecordArgPassingKind::CanPassInRegs);
|
2022-04-09 06:36:51 +00:00
|
|
|
setIsRandomized(false);
|
2022-12-02 02:39:23 +00:00
|
|
|
setODRHash(0);
|
2008-09-02 21:12:32 +00:00
|
|
|
}
|
|
|
|
|
2011-01-12 09:06:06 +00:00
|
|
|
RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC,
|
2011-03-09 14:09:51 +00:00
|
|
|
SourceLocation StartLoc, SourceLocation IdLoc,
|
|
|
|
IdentifierInfo *Id, RecordDecl* PrevDecl) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-16 23:01:30 +00:00
|
|
|
RecordDecl *R = new (C, DC) RecordDecl(Record, TK, C, DC,
|
|
|
|
StartLoc, IdLoc, Id, PrevDecl);
|
2018-08-01 20:48:16 +00:00
|
|
|
R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
|
Ensure that type definitions present in just-loaded modules are
visible.
The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,
class X;
X *x;
and then import a module that includes a definition of X:
import XDef;
We will then fail when attempting to access a member of X, e.g.,
x->method()
because the AST reader did not know to look for a default of a class
named X within the new module.
This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.
In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,
// module 1
namespace N { struct X; }
// module 2
namespace N { struct X { /* ... */ }; }
One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.
llvm-svn: 174794
2013-02-09 01:35:03 +00:00
|
|
|
|
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;
|
2008-09-02 21:12:32 +00:00
|
|
|
}
|
|
|
|
|
2012-01-05 21:55:30 +00:00
|
|
|
RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
|
2023-11-03 17:45:39 +00:00
|
|
|
RecordDecl *R = new (C, ID)
|
|
|
|
RecordDecl(Record, TagTypeKind::Struct, C, nullptr, SourceLocation(),
|
|
|
|
SourceLocation(), nullptr, nullptr);
|
2018-08-01 20:48:16 +00:00
|
|
|
R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
|
Ensure that type definitions present in just-loaded modules are
visible.
The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,
class X;
X *x;
and then import a module that includes a definition of X:
import XDef;
We will then fail when attempting to access a member of X, e.g.,
x->method()
because the AST reader did not know to look for a default of a class
named X within the new module.
This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.
In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,
// module 1
namespace N { struct X; }
// module 2
namespace N { struct X { /* ... */ }; }
One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.
llvm-svn: 174794
2013-02-09 01:35:03 +00:00
|
|
|
return R;
|
2010-07-02 11:54:55 +00:00
|
|
|
}
|
|
|
|
|
2009-03-25 15:59:44 +00:00
|
|
|
bool RecordDecl::isInjectedClassName() const {
|
2009-09-09 15:08:12 +00:00
|
|
|
return isImplicit() && getDeclName() && getDeclContext()->isRecord() &&
|
2009-03-25 15:59:44 +00:00
|
|
|
cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName();
|
|
|
|
}
|
|
|
|
|
2014-08-28 04:28:19 +00:00
|
|
|
bool RecordDecl::isLambda() const {
|
|
|
|
if (auto RD = dyn_cast<CXXRecordDecl>(this))
|
|
|
|
return RD->isLambda();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-10-29 12:21:55 +00:00
|
|
|
bool RecordDecl::isCapturedRecord() const {
|
|
|
|
return hasAttr<CapturedRecordAttr>();
|
|
|
|
}
|
|
|
|
|
|
|
|
void RecordDecl::setCapturedRecord() {
|
|
|
|
addAttr(CapturedRecordAttr::CreateImplicit(getASTContext()));
|
|
|
|
}
|
|
|
|
|
[CMSE] Clear padding bits of struct/unions/fp16 passed by value
When passing a value of a struct/union type from secure to non-secure
state (that is returning from a CMSE entry function or passing an
argument to CMSE-non-secure call), there is a potential sensitive
information leak via the padding bits in the structure. It is not
possible in the general case to ensure those bits are cleared by using
Standard C/C++.
This patch makes the compiler emit code to clear such padding
bits. Since type information is lost in LLVM IR, the code generation
is done by Clang.
For each interesting record type, we build a bitmask, in which all the
bits, corresponding to user declared members, are set. Values of
record types are returned by coercing them to an integer. After the
coercion, the coerced value is masked (with bitwise AND) and then
returned by the function. In a similar manner, values of record types
are passed as arguments by coercing them to an array of integers, and
the coerced values themselves are masked.
For union types, we effectively clear only bits, which aren't part of
any member, since we don't know which is the currently active one.
The compiler will issue a warning, whenever a union is passed to
non-secure state.
Values of half-precision floating-point types are passed in the least
significant bits of a 32-bit register (GPR or FPR) with the most
significant bits unspecified. Since this is also a potential leak of
sensitive information, this patch also clears those unspecified bits.
Differential Revision: https://reviews.llvm.org/D76369
2020-04-28 15:27:52 +00:00
|
|
|
bool RecordDecl::isOrContainsUnion() const {
|
|
|
|
if (isUnion())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (const RecordDecl *Def = getDefinition()) {
|
|
|
|
for (const FieldDecl *FD : Def->fields()) {
|
|
|
|
const RecordType *RT = FD->getType()->getAs<RecordType>();
|
|
|
|
if (RT && RT->getDecl()->isOrContainsUnion())
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-10-14 20:14:34 +00:00
|
|
|
RecordDecl::field_iterator RecordDecl::field_begin() const {
|
2018-08-01 20:48:16 +00:00
|
|
|
if (hasExternalLexicalStorage() && !hasLoadedFieldsFromExternalStorage())
|
2010-10-14 20:14:34 +00:00
|
|
|
LoadFieldsFromExternalStorage();
|
2023-01-23 18:15:46 +00:00
|
|
|
// This is necessary for correctness for C++ with modules.
|
|
|
|
// FIXME: Come up with a test case that breaks without definition.
|
|
|
|
if (RecordDecl *D = getDefinition(); D && D != this)
|
|
|
|
return D->field_begin();
|
2010-10-14 20:14:34 +00:00
|
|
|
return field_iterator(decl_iterator(FirstDecl));
|
|
|
|
}
|
|
|
|
|
2011-02-19 18:51:44 +00:00
|
|
|
/// completeDefinition - Notes that the definition of this type is now
|
|
|
|
/// complete.
|
|
|
|
void RecordDecl::completeDefinition() {
|
2011-10-07 06:10:15 +00:00
|
|
|
assert(!isCompleteDefinition() && "Cannot redefine record!");
|
2011-02-19 18:51:44 +00:00
|
|
|
TagDecl::completeDefinition();
|
2021-06-21 19:37:10 +00:00
|
|
|
|
|
|
|
ASTContext &Ctx = getASTContext();
|
|
|
|
|
|
|
|
// Layouts are dumped when computed, so if we are dumping for all complete
|
|
|
|
// types, we need to force usage to get types that wouldn't be used elsewhere.
|
|
|
|
if (Ctx.getLangOpts().DumpRecordLayoutsComplete)
|
|
|
|
(void)Ctx.getASTRecordLayout(this);
|
2011-02-19 18:51:44 +00:00
|
|
|
}
|
|
|
|
|
2012-10-12 23:29:20 +00:00
|
|
|
/// isMsStruct - Get whether or not this record uses ms_struct layout.
|
|
|
|
/// This which can be turned on with an attribute, pragma, or the
|
|
|
|
/// -mms-bitfields command-line option.
|
|
|
|
bool RecordDecl::isMsStruct(const ASTContext &C) const {
|
2015-02-02 19:30:52 +00:00
|
|
|
return hasAttr<MSStructAttr>() || C.getLangOpts().MSBitfields == 1;
|
2012-10-12 23:29:20 +00:00
|
|
|
}
|
|
|
|
|
2022-04-28 19:00:47 +00:00
|
|
|
void RecordDecl::reorderDecls(const SmallVectorImpl<Decl *> &Decls) {
|
|
|
|
std::tie(FirstDecl, LastDecl) = DeclContext::BuildDeclChain(Decls, false);
|
2022-04-09 06:36:51 +00:00
|
|
|
LastDecl->NextInContextAndBits.setPointer(nullptr);
|
|
|
|
setIsRandomized(true);
|
|
|
|
}
|
|
|
|
|
2010-10-14 20:14:34 +00:00
|
|
|
void RecordDecl::LoadFieldsFromExternalStorage() const {
|
|
|
|
ExternalASTSource *Source = getASTContext().getExternalSource();
|
|
|
|
assert(hasExternalLexicalStorage() && Source && "No external storage?");
|
|
|
|
|
|
|
|
// Notify that we have a RecordDecl doing some initialization.
|
|
|
|
ExternalASTSource::Deserializing TheFields(Source);
|
|
|
|
|
2011-07-23 10:55:15 +00:00
|
|
|
SmallVector<Decl*, 64> Decls;
|
2018-08-01 20:48:16 +00:00
|
|
|
setHasLoadedFieldsFromExternalStorage(true);
|
2015-08-05 22:41:45 +00:00
|
|
|
Source->FindExternalLexicalDecls(this, [](Decl::Kind K) {
|
|
|
|
return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K);
|
|
|
|
}, Decls);
|
2010-10-14 20:14:34 +00:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
// Check that all decls we got were FieldDecls.
|
|
|
|
for (unsigned i=0, e=Decls.size(); i != e; ++i)
|
2012-09-10 22:04:22 +00:00
|
|
|
assert(isa<FieldDecl>(Decls[i]) || isa<IndirectFieldDecl>(Decls[i]));
|
2010-10-14 20:14:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (Decls.empty())
|
|
|
|
return;
|
|
|
|
|
2023-04-17 12:02:48 +00:00
|
|
|
auto [ExternalFirst, ExternalLast] =
|
|
|
|
BuildDeclChain(Decls,
|
|
|
|
/*FieldsAlreadyLoaded=*/false);
|
|
|
|
ExternalLast->NextInContextAndBits.setPointer(FirstDecl);
|
|
|
|
FirstDecl = ExternalFirst;
|
|
|
|
if (!LastDecl)
|
|
|
|
LastDecl = ExternalLast;
|
2010-10-14 20:14:34 +00:00
|
|
|
}
|
|
|
|
|
2014-10-16 20:54:52 +00:00
|
|
|
bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const {
|
|
|
|
ASTContext &Context = getASTContext();
|
2017-09-25 22:11:12 +00:00
|
|
|
const SanitizerMask EnabledAsanMask = Context.getLangOpts().Sanitize.Mask &
|
|
|
|
(SanitizerKind::Address | SanitizerKind::KernelAddress);
|
|
|
|
if (!EnabledAsanMask || !Context.getLangOpts().SanitizeAddressFieldPadding)
|
2014-10-16 20:54:52 +00:00
|
|
|
return false;
|
2021-02-22 19:47:29 +00:00
|
|
|
const auto &NoSanitizeList = Context.getNoSanitizeList();
|
2015-11-09 17:53:06 +00:00
|
|
|
const auto *CXXRD = dyn_cast<CXXRecordDecl>(this);
|
2014-10-16 20:54:52 +00:00
|
|
|
// We may be able to relax some of these requirements.
|
|
|
|
int ReasonToReject = -1;
|
|
|
|
if (!CXXRD || CXXRD->isExternCContext())
|
|
|
|
ReasonToReject = 0; // is not C++.
|
|
|
|
else if (CXXRD->hasAttr<PackedAttr>())
|
|
|
|
ReasonToReject = 1; // is packed.
|
|
|
|
else if (CXXRD->isUnion())
|
|
|
|
ReasonToReject = 2; // is a union.
|
|
|
|
else if (CXXRD->isTriviallyCopyable())
|
|
|
|
ReasonToReject = 3; // is trivially copyable.
|
|
|
|
else if (CXXRD->hasTrivialDestructor())
|
|
|
|
ReasonToReject = 4; // has trivial destructor.
|
|
|
|
else if (CXXRD->isStandardLayout())
|
|
|
|
ReasonToReject = 5; // is standard layout.
|
2021-02-22 19:47:29 +00:00
|
|
|
else if (NoSanitizeList.containsLocation(EnabledAsanMask, getLocation(),
|
2017-09-25 22:11:12 +00:00
|
|
|
"field-padding"))
|
2020-06-20 23:02:27 +00:00
|
|
|
ReasonToReject = 6; // is in an excluded file.
|
2021-02-22 19:47:29 +00:00
|
|
|
else if (NoSanitizeList.containsType(
|
|
|
|
EnabledAsanMask, getQualifiedNameAsString(), "field-padding"))
|
2020-06-20 23:02:27 +00:00
|
|
|
ReasonToReject = 7; // The type is excluded.
|
2014-10-16 20:54:52 +00:00
|
|
|
|
|
|
|
if (EmitRemark) {
|
|
|
|
if (ReasonToReject >= 0)
|
|
|
|
Context.getDiagnostics().Report(
|
|
|
|
getLocation(),
|
|
|
|
diag::remark_sanitize_address_insert_extra_padding_rejected)
|
|
|
|
<< getQualifiedNameAsString() << ReasonToReject;
|
|
|
|
else
|
|
|
|
Context.getDiagnostics().Report(
|
|
|
|
getLocation(),
|
|
|
|
diag::remark_sanitize_address_insert_extra_padding_accepted)
|
|
|
|
<< getQualifiedNameAsString();
|
|
|
|
}
|
|
|
|
return ReasonToReject < 0;
|
|
|
|
}
|
|
|
|
|
2014-12-12 16:17:46 +00:00
|
|
|
const FieldDecl *RecordDecl::findFirstNamedDataMember() const {
|
|
|
|
for (const auto *I : fields()) {
|
|
|
|
if (I->getIdentifier())
|
|
|
|
return I;
|
|
|
|
|
2015-11-09 17:53:06 +00:00
|
|
|
if (const auto *RT = I->getType()->getAs<RecordType>())
|
2014-12-12 16:17:46 +00:00
|
|
|
if (const FieldDecl *NamedDataMember =
|
2015-11-09 17:53:06 +00:00
|
|
|
RT->getDecl()->findFirstNamedDataMember())
|
2014-12-12 16:17:46 +00:00
|
|
|
return NamedDataMember;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We didn't find a named data member.
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-12-02 02:39:23 +00:00
|
|
|
unsigned RecordDecl::getODRHash() {
|
|
|
|
if (hasODRHash())
|
|
|
|
return RecordDeclBits.ODRHash;
|
|
|
|
|
|
|
|
// Only calculate hash on first call of getODRHash per record.
|
|
|
|
ODRHash Hash;
|
|
|
|
Hash.AddRecordDecl(this);
|
|
|
|
// For RecordDecl the ODRHash is stored in the remaining 26
|
|
|
|
// bit of RecordDeclBits, adjust the hash to accomodate.
|
|
|
|
setODRHash(Hash.CalculateHash() >> 6);
|
|
|
|
return RecordDeclBits.ODRHash;
|
|
|
|
}
|
|
|
|
|
2008-10-08 17:01:13 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// BlockDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-08-01 21:16:54 +00:00
|
|
|
BlockDecl::BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
|
|
|
|
: Decl(Block, DC, CaretLoc), DeclContext(Block) {
|
|
|
|
setIsVariadic(false);
|
|
|
|
setCapturesCXXThis(false);
|
|
|
|
setBlockMissingReturnType(true);
|
|
|
|
setIsConversionFromLambda(false);
|
|
|
|
setDoesNotEscape(false);
|
2019-02-27 18:17:16 +00:00
|
|
|
setCanAvoidCopyToHeap(false);
|
2018-08-01 21:16:54 +00:00
|
|
|
}
|
|
|
|
|
2013-01-12 19:30:44 +00:00
|
|
|
void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) {
|
2014-05-12 05:36:57 +00:00
|
|
|
assert(!ParamInfo && "Already has param info!");
|
2009-09-09 15:08:12 +00:00
|
|
|
|
2009-03-13 16:56:44 +00:00
|
|
|
// Zero params -> null pointer.
|
2011-09-21 18:16:56 +00:00
|
|
|
if (!NewParamInfo.empty()) {
|
|
|
|
NumParams = NewParamInfo.size();
|
|
|
|
ParamInfo = new (getASTContext()) ParmVarDecl*[NewParamInfo.size()];
|
|
|
|
std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo);
|
2009-03-13 16:56:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-05 09:40:35 +00:00
|
|
|
void BlockDecl::setCaptures(ASTContext &Context, ArrayRef<Capture> Captures,
|
|
|
|
bool CapturesCXXThis) {
|
2018-08-01 21:16:54 +00:00
|
|
|
this->setCapturesCXXThis(CapturesCXXThis);
|
2015-08-05 09:40:35 +00:00
|
|
|
this->NumCaptures = Captures.size();
|
|
|
|
|
|
|
|
if (Captures.empty()) {
|
|
|
|
this->Captures = nullptr;
|
2011-02-02 13:00:07 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-08-05 09:40:35 +00:00
|
|
|
this->Captures = Captures.copy(Context).data();
|
2009-03-13 16:56:44 +00:00
|
|
|
}
|
2010-01-26 22:01:41 +00:00
|
|
|
|
2011-06-15 22:51:16 +00:00
|
|
|
bool BlockDecl::capturesVariable(const VarDecl *variable) const {
|
2014-03-14 18:34:04 +00:00
|
|
|
for (const auto &I : captures())
|
2011-06-15 22:51:16 +00:00
|
|
|
// Only auto vars can be captured, so no redeclaration worries.
|
2014-03-14 18:34:04 +00:00
|
|
|
if (I.getVariable() == variable)
|
2011-06-15 22:51:16 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-12-21 16:27:07 +00:00
|
|
|
SourceRange BlockDecl::getSourceRange() const {
|
2018-08-09 21:09:38 +00:00
|
|
|
return SourceRange(getLocation(), Body ? Body->getEndLoc() : getLocation());
|
2010-12-21 16:27:07 +00:00
|
|
|
}
|
2010-01-26 22:01:41 +00:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Other Decl Allocation/Deallocation Method Implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-11-13 23:01:27 +00:00
|
|
|
void TranslationUnitDecl::anchor() {}
|
2011-12-20 02:48:34 +00:00
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
|
2014-05-12 05:36:57 +00:00
|
|
|
return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C);
|
2010-01-26 22:01:41 +00:00
|
|
|
}
|
|
|
|
|
2017-11-13 23:01:27 +00:00
|
|
|
void PragmaCommentDecl::anchor() {}
|
2016-03-02 17:28:48 +00:00
|
|
|
|
|
|
|
PragmaCommentDecl *PragmaCommentDecl::Create(const ASTContext &C,
|
|
|
|
TranslationUnitDecl *DC,
|
|
|
|
SourceLocation CommentLoc,
|
|
|
|
PragmaMSCommentKind CommentKind,
|
|
|
|
StringRef Arg) {
|
|
|
|
PragmaCommentDecl *PCD =
|
|
|
|
new (C, DC, additionalSizeToAlloc<char>(Arg.size() + 1))
|
|
|
|
PragmaCommentDecl(DC, CommentLoc, CommentKind);
|
|
|
|
memcpy(PCD->getTrailingObjects<char>(), Arg.data(), Arg.size());
|
|
|
|
PCD->getTrailingObjects<char>()[Arg.size()] = '\0';
|
|
|
|
return PCD;
|
|
|
|
}
|
|
|
|
|
|
|
|
PragmaCommentDecl *PragmaCommentDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID,
|
|
|
|
unsigned ArgSize) {
|
|
|
|
return new (C, ID, additionalSizeToAlloc<char>(ArgSize + 1))
|
|
|
|
PragmaCommentDecl(nullptr, SourceLocation(), PCK_Unknown);
|
|
|
|
}
|
|
|
|
|
2017-11-13 23:01:27 +00:00
|
|
|
void PragmaDetectMismatchDecl::anchor() {}
|
2016-03-02 19:28:54 +00:00
|
|
|
|
|
|
|
PragmaDetectMismatchDecl *
|
|
|
|
PragmaDetectMismatchDecl::Create(const ASTContext &C, TranslationUnitDecl *DC,
|
|
|
|
SourceLocation Loc, StringRef Name,
|
|
|
|
StringRef Value) {
|
|
|
|
size_t ValueStart = Name.size() + 1;
|
|
|
|
PragmaDetectMismatchDecl *PDMD =
|
|
|
|
new (C, DC, additionalSizeToAlloc<char>(ValueStart + Value.size() + 1))
|
|
|
|
PragmaDetectMismatchDecl(DC, Loc, ValueStart);
|
|
|
|
memcpy(PDMD->getTrailingObjects<char>(), Name.data(), Name.size());
|
|
|
|
PDMD->getTrailingObjects<char>()[Name.size()] = '\0';
|
|
|
|
memcpy(PDMD->getTrailingObjects<char>() + ValueStart, Value.data(),
|
|
|
|
Value.size());
|
|
|
|
PDMD->getTrailingObjects<char>()[ValueStart + Value.size()] = '\0';
|
|
|
|
return PDMD;
|
|
|
|
}
|
|
|
|
|
|
|
|
PragmaDetectMismatchDecl *
|
|
|
|
PragmaDetectMismatchDecl::CreateDeserialized(ASTContext &C, unsigned ID,
|
|
|
|
unsigned NameValueSize) {
|
|
|
|
return new (C, ID, additionalSizeToAlloc<char>(NameValueSize + 1))
|
|
|
|
PragmaDetectMismatchDecl(nullptr, SourceLocation(), 0);
|
|
|
|
}
|
2016-03-02 17:28:48 +00:00
|
|
|
|
2017-11-13 23:01:27 +00:00
|
|
|
void ExternCContextDecl::anchor() {}
|
2015-03-07 00:04:49 +00:00
|
|
|
|
|
|
|
ExternCContextDecl *ExternCContextDecl::Create(const ASTContext &C,
|
|
|
|
TranslationUnitDecl *DC) {
|
|
|
|
return new (C, DC) ExternCContextDecl(DC);
|
|
|
|
}
|
|
|
|
|
2017-11-13 23:01:27 +00:00
|
|
|
void LabelDecl::anchor() {}
|
2011-12-20 02:48:34 +00:00
|
|
|
|
2011-02-17 07:39:24 +00:00
|
|
|
LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
|
2011-03-05 18:21:20 +00:00
|
|
|
SourceLocation IdentL, IdentifierInfo *II) {
|
2014-05-12 05:36:57 +00:00
|
|
|
return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, IdentL);
|
2011-03-05 18:21:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation IdentL, IdentifierInfo *II,
|
|
|
|
SourceLocation GnuLabelL) {
|
|
|
|
assert(GnuLabelL != IdentL && "Use this only for GNU local labels");
|
2014-05-12 05:36:57 +00:00
|
|
|
return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, GnuLabelL);
|
2011-02-17 07:39:24 +00:00
|
|
|
}
|
|
|
|
|
2012-01-05 21:55:30 +00:00
|
|
|
LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2014-05-12 05:36:57 +00:00
|
|
|
return new (C, ID) LabelDecl(nullptr, SourceLocation(), nullptr, nullptr,
|
|
|
|
SourceLocation());
|
2010-10-27 19:49:05 +00:00
|
|
|
}
|
|
|
|
|
2014-09-22 02:21:54 +00:00
|
|
|
void LabelDecl::setMSAsmLabel(StringRef Name) {
|
2019-12-05 23:30:21 +00:00
|
|
|
char *Buffer = new (getASTContext(), 1) char[Name.size() + 1];
|
2014-09-22 02:21:54 +00:00
|
|
|
memcpy(Buffer, Name.data(), Name.size());
|
|
|
|
Buffer[Name.size()] = '\0';
|
|
|
|
MSAsmName = Buffer;
|
|
|
|
}
|
|
|
|
|
2017-11-13 23:01:27 +00:00
|
|
|
void ValueDecl::anchor() {}
|
2011-12-20 02:48:34 +00:00
|
|
|
|
2012-12-01 15:09:41 +00:00
|
|
|
bool ValueDecl::isWeak() const {
|
2020-09-02 21:42:37 +00:00
|
|
|
auto *MostRecent = getMostRecentDecl();
|
|
|
|
return MostRecent->hasAttr<WeakAttr>() ||
|
|
|
|
MostRecent->hasAttr<WeakRefAttr>() || isWeakImported();
|
2012-12-01 15:09:41 +00:00
|
|
|
}
|
|
|
|
|
2022-03-30 12:27:44 +00:00
|
|
|
bool ValueDecl::isInitCapture() const {
|
|
|
|
if (auto *Var = llvm::dyn_cast<VarDecl>(this))
|
|
|
|
return Var->isInitCapture();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-13 23:01:27 +00:00
|
|
|
void ImplicitParamDecl::anchor() {}
|
2011-12-20 02:48:34 +00:00
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
|
2011-03-08 08:55:46 +00:00
|
|
|
SourceLocation IdLoc,
|
2017-06-09 13:40:18 +00:00
|
|
|
IdentifierInfo *Id, QualType Type,
|
|
|
|
ImplicitParamKind ParamKind) {
|
|
|
|
return new (C, DC) ImplicitParamDecl(C, DC, IdLoc, Id, Type, ParamKind);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, QualType Type,
|
|
|
|
ImplicitParamKind ParamKind) {
|
|
|
|
return new (C, nullptr) ImplicitParamDecl(C, Type, ParamKind);
|
2010-01-26 22:01:41 +00:00
|
|
|
}
|
|
|
|
|
2013-11-22 09:01:48 +00:00
|
|
|
ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C,
|
2012-01-05 21:55:30 +00:00
|
|
|
unsigned ID) {
|
2017-06-09 13:40:18 +00:00
|
|
|
return new (C, ID) ImplicitParamDecl(C, QualType(), ImplicitParamKind::Other);
|
2012-01-05 21:55:30 +00:00
|
|
|
}
|
|
|
|
|
2021-07-29 16:02:20 +00:00
|
|
|
FunctionDecl *
|
|
|
|
FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
|
|
|
const DeclarationNameInfo &NameInfo, QualType T,
|
|
|
|
TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin,
|
|
|
|
bool isInlineSpecified, bool hasWrittenPrototype,
|
|
|
|
ConstexprSpecKind ConstexprKind,
|
|
|
|
Expr *TrailingRequiresClause) {
|
|
|
|
FunctionDecl *New = new (C, DC) FunctionDecl(
|
|
|
|
Function, C, DC, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin,
|
|
|
|
isInlineSpecified, ConstexprKind, TrailingRequiresClause);
|
2018-08-01 21:02:40 +00:00
|
|
|
New->setHasWrittenPrototype(hasWrittenPrototype);
|
2010-01-26 22:01:41 +00:00
|
|
|
return New;
|
|
|
|
}
|
|
|
|
|
2012-01-05 21:55:30 +00:00
|
|
|
FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2021-01-04 22:17:45 +00:00
|
|
|
return new (C, ID) FunctionDecl(
|
|
|
|
Function, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(),
|
2021-07-29 16:02:20 +00:00
|
|
|
nullptr, SC_None, false, false, ConstexprSpecKind::Unspecified, nullptr);
|
2012-01-05 21:55:30 +00:00
|
|
|
}
|
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
|
2013-11-22 09:01:48 +00:00
|
|
|
return new (C, DC) BlockDecl(DC, L);
|
2010-01-26 22:01:41 +00:00
|
|
|
}
|
|
|
|
|
2012-01-05 21:55:30 +00:00
|
|
|
BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2014-05-12 05:36:57 +00:00
|
|
|
return new (C, ID) BlockDecl(nullptr, SourceLocation());
|
2013-04-16 07:28:30 +00:00
|
|
|
}
|
|
|
|
|
2015-12-30 03:24:14 +00:00
|
|
|
CapturedDecl::CapturedDecl(DeclContext *DC, unsigned NumParams)
|
|
|
|
: Decl(Captured, DC, SourceLocation()), DeclContext(Captured),
|
|
|
|
NumParams(NumParams), ContextParam(0), BodyAndNothrow(nullptr, false) {}
|
|
|
|
|
2013-05-03 19:00:33 +00:00
|
|
|
CapturedDecl *CapturedDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
unsigned NumParams) {
|
2015-08-06 20:26:32 +00:00
|
|
|
return new (C, DC, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams))
|
2013-11-22 09:01:48 +00:00
|
|
|
CapturedDecl(DC, NumParams);
|
2013-04-16 19:37:38 +00:00
|
|
|
}
|
|
|
|
|
2013-05-03 19:20:19 +00:00
|
|
|
CapturedDecl *CapturedDecl::CreateDeserialized(ASTContext &C, unsigned ID,
|
2013-11-22 09:01:48 +00:00
|
|
|
unsigned NumParams) {
|
2015-08-06 20:26:32 +00:00
|
|
|
return new (C, ID, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams))
|
2014-05-12 05:36:57 +00:00
|
|
|
CapturedDecl(nullptr, NumParams);
|
2013-05-03 19:20:19 +00:00
|
|
|
}
|
|
|
|
|
2015-12-30 03:24:14 +00:00
|
|
|
Stmt *CapturedDecl::getBody() const { return BodyAndNothrow.getPointer(); }
|
|
|
|
void CapturedDecl::setBody(Stmt *B) { BodyAndNothrow.setPointer(B); }
|
|
|
|
|
|
|
|
bool CapturedDecl::isNothrow() const { return BodyAndNothrow.getInt(); }
|
|
|
|
void CapturedDecl::setNothrow(bool Nothrow) { BodyAndNothrow.setInt(Nothrow); }
|
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
|
|
|
|
SourceLocation L,
|
|
|
|
IdentifierInfo *Id, QualType T,
|
|
|
|
Expr *E, const llvm::APSInt &V) {
|
2013-11-22 09:01:48 +00:00
|
|
|
return new (C, CD) EnumConstantDecl(CD, L, Id, T, E, V);
|
2010-01-26 22:01:41 +00:00
|
|
|
}
|
|
|
|
|
2012-01-05 21:55:30 +00:00
|
|
|
EnumConstantDecl *
|
|
|
|
EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2014-05-12 05:36:57 +00:00
|
|
|
return new (C, ID) EnumConstantDecl(nullptr, SourceLocation(), nullptr,
|
|
|
|
QualType(), nullptr, llvm::APSInt());
|
2012-01-05 21:55:30 +00:00
|
|
|
}
|
|
|
|
|
2017-11-13 23:01:27 +00:00
|
|
|
void IndirectFieldDecl::anchor() {}
|
2011-12-20 02:48:34 +00:00
|
|
|
|
2016-01-06 22:49:11 +00:00
|
|
|
IndirectFieldDecl::IndirectFieldDecl(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation L, DeclarationName N,
|
2016-06-24 04:05:48 +00:00
|
|
|
QualType T,
|
|
|
|
MutableArrayRef<NamedDecl *> CH)
|
|
|
|
: ValueDecl(IndirectField, DC, L, N, T), Chaining(CH.data()),
|
|
|
|
ChainingSize(CH.size()) {
|
2016-01-06 22:49:11 +00:00
|
|
|
// In C++, indirect field declarations conflict with tag declarations in the
|
|
|
|
// same scope, so add them to IDNS_Tag so that tag redeclaration finds them.
|
|
|
|
if (C.getLangOpts().CPlusPlus)
|
|
|
|
IdentifierNamespace |= IDNS_Tag;
|
|
|
|
}
|
|
|
|
|
2010-11-21 14:11:41 +00:00
|
|
|
IndirectFieldDecl *
|
|
|
|
IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
2016-06-24 04:05:48 +00:00
|
|
|
IdentifierInfo *Id, QualType T,
|
|
|
|
llvm::MutableArrayRef<NamedDecl *> CH) {
|
|
|
|
return new (C, DC) IndirectFieldDecl(C, DC, L, Id, T, CH);
|
2010-11-21 06:08:52 +00:00
|
|
|
}
|
|
|
|
|
2012-01-05 21:55:30 +00:00
|
|
|
IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
2022-12-03 19:13:41 +00:00
|
|
|
return new (C, ID)
|
|
|
|
IndirectFieldDecl(C, nullptr, SourceLocation(), DeclarationName(),
|
|
|
|
QualType(), std::nullopt);
|
2012-01-05 21:55:30 +00:00
|
|
|
}
|
|
|
|
|
2010-09-01 20:41:53 +00:00
|
|
|
SourceRange EnumConstantDecl::getSourceRange() const {
|
|
|
|
SourceLocation End = getLocation();
|
|
|
|
if (Init)
|
2018-08-09 21:09:38 +00:00
|
|
|
End = Init->getEndLoc();
|
2010-09-01 20:41:53 +00:00
|
|
|
return SourceRange(getLocation(), End);
|
|
|
|
}
|
|
|
|
|
2017-11-13 23:01:27 +00:00
|
|
|
void TypeDecl::anchor() {}
|
2011-12-20 02:48:34 +00:00
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
|
2011-03-06 15:48:19 +00:00
|
|
|
SourceLocation StartLoc, SourceLocation IdLoc,
|
|
|
|
IdentifierInfo *Id, TypeSourceInfo *TInfo) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-16 23:01:30 +00:00
|
|
|
return new (C, DC) TypedefDecl(C, DC, StartLoc, IdLoc, Id, TInfo);
|
2010-01-26 22:01:41 +00:00
|
|
|
}
|
|
|
|
|
2017-11-13 23:01:27 +00:00
|
|
|
void TypedefNameDecl::anchor() {}
|
2011-12-20 02:48:34 +00:00
|
|
|
|
2015-05-15 20:05:43 +00:00
|
|
|
TagDecl *TypedefNameDecl::getAnonDeclWithTypedefName(bool AnyRedecl) const {
|
|
|
|
if (auto *TT = getTypeSourceInfo()->getType()->getAs<TagType>()) {
|
|
|
|
auto *OwningTypedef = TT->getDecl()->getTypedefNameForAnonDecl();
|
|
|
|
auto *ThisTypedef = this;
|
|
|
|
if (AnyRedecl && OwningTypedef) {
|
|
|
|
OwningTypedef = OwningTypedef->getCanonicalDecl();
|
|
|
|
ThisTypedef = ThisTypedef->getCanonicalDecl();
|
|
|
|
}
|
|
|
|
if (OwningTypedef == ThisTypedef)
|
2015-03-27 01:37:43 +00:00
|
|
|
return TT->getDecl();
|
2015-05-15 20:05:43 +00:00
|
|
|
}
|
2015-03-27 01:37:43 +00:00
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-03-21 16:56:02 +00:00
|
|
|
bool TypedefNameDecl::isTransparentTagSlow() const {
|
|
|
|
auto determineIsTransparent = [&]() {
|
|
|
|
if (auto *TT = getUnderlyingType()->getAs<TagType>()) {
|
|
|
|
if (auto *TD = TT->getDecl()) {
|
|
|
|
if (TD->getName() != getName())
|
|
|
|
return false;
|
|
|
|
SourceLocation TTLoc = getLocation();
|
|
|
|
SourceLocation TDLoc = TD->getLocation();
|
|
|
|
if (!TTLoc.isMacroID() || !TDLoc.isMacroID())
|
|
|
|
return false;
|
|
|
|
SourceManager &SM = getASTContext().getSourceManager();
|
|
|
|
return SM.getSpellingLoc(TTLoc) == SM.getSpellingLoc(TDLoc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
bool isTransparent = determineIsTransparent();
|
2018-01-26 14:14:11 +00:00
|
|
|
MaybeModedTInfo.setInt((isTransparent << 1) | 1);
|
2017-03-21 16:56:02 +00:00
|
|
|
return isTransparent;
|
|
|
|
}
|
|
|
|
|
2012-01-05 21:55:30 +00:00
|
|
|
TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-16 23:01:30 +00:00
|
|
|
return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(),
|
2014-05-12 05:36:57 +00:00
|
|
|
nullptr, nullptr);
|
2012-01-05 21:55:30 +00:00
|
|
|
}
|
|
|
|
|
2011-04-15 14:24:37 +00:00
|
|
|
TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc, IdentifierInfo *Id,
|
|
|
|
TypeSourceInfo *TInfo) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-16 23:01:30 +00:00
|
|
|
return new (C, DC) TypeAliasDecl(C, DC, StartLoc, IdLoc, Id, TInfo);
|
2011-04-15 14:24:37 +00:00
|
|
|
}
|
|
|
|
|
2012-01-05 21:55:30 +00:00
|
|
|
TypeAliasDecl *TypeAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-16 23:01:30 +00:00
|
|
|
return new (C, ID) TypeAliasDecl(C, nullptr, SourceLocation(),
|
|
|
|
SourceLocation(), nullptr, nullptr);
|
2012-01-05 21:55:30 +00:00
|
|
|
}
|
|
|
|
|
2011-03-08 16:41:52 +00:00
|
|
|
SourceRange TypedefDecl::getSourceRange() const {
|
|
|
|
SourceLocation RangeEnd = getLocation();
|
|
|
|
if (TypeSourceInfo *TInfo = getTypeSourceInfo()) {
|
|
|
|
if (typeIsPostfix(TInfo->getType()))
|
|
|
|
RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd();
|
|
|
|
}
|
2018-08-09 21:08:08 +00:00
|
|
|
return SourceRange(getBeginLoc(), RangeEnd);
|
2011-03-08 16:41:52 +00:00
|
|
|
}
|
|
|
|
|
2011-04-15 14:24:37 +00:00
|
|
|
SourceRange TypeAliasDecl::getSourceRange() const {
|
2018-08-09 21:08:08 +00:00
|
|
|
SourceLocation RangeEnd = getBeginLoc();
|
2011-04-15 14:24:37 +00:00
|
|
|
if (TypeSourceInfo *TInfo = getTypeSourceInfo())
|
|
|
|
RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd();
|
2018-08-09 21:08:08 +00:00
|
|
|
return SourceRange(getBeginLoc(), RangeEnd);
|
2011-04-15 14:24:37 +00:00
|
|
|
}
|
|
|
|
|
2017-11-13 23:01:27 +00:00
|
|
|
void FileScopeAsmDecl::anchor() {}
|
2011-12-20 02:48:34 +00:00
|
|
|
|
2010-01-26 22:01:41 +00:00
|
|
|
FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
|
2011-03-03 14:20:18 +00:00
|
|
|
StringLiteral *Str,
|
|
|
|
SourceLocation AsmLoc,
|
|
|
|
SourceLocation RParenLoc) {
|
2013-11-22 09:01:48 +00:00
|
|
|
return new (C, DC) FileScopeAsmDecl(DC, Str, AsmLoc, RParenLoc);
|
2010-01-26 22:01:41 +00:00
|
|
|
}
|
2011-12-02 23:23:56 +00:00
|
|
|
|
2013-11-22 09:01:48 +00:00
|
|
|
FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C,
|
2012-01-05 21:55:30 +00:00
|
|
|
unsigned ID) {
|
2014-05-12 05:36:57 +00:00
|
|
|
return new (C, ID) FileScopeAsmDecl(nullptr, nullptr, SourceLocation(),
|
|
|
|
SourceLocation());
|
2012-01-05 21:55:30 +00:00
|
|
|
}
|
|
|
|
|
2022-06-08 09:59:40 +00:00
|
|
|
void TopLevelStmtDecl::anchor() {}
|
|
|
|
|
|
|
|
TopLevelStmtDecl *TopLevelStmtDecl::Create(ASTContext &C, Stmt *Statement) {
|
|
|
|
assert(Statement);
|
|
|
|
assert(C.getLangOpts().IncrementalExtensions &&
|
|
|
|
"Must be used only in incremental mode");
|
|
|
|
|
|
|
|
SourceLocation BeginLoc = Statement->getBeginLoc();
|
|
|
|
DeclContext *DC = C.getTranslationUnitDecl();
|
|
|
|
|
|
|
|
return new (C, DC) TopLevelStmtDecl(DC, BeginLoc, Statement);
|
|
|
|
}
|
|
|
|
|
|
|
|
TopLevelStmtDecl *TopLevelStmtDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
|
|
|
return new (C, ID)
|
|
|
|
TopLevelStmtDecl(/*DC=*/nullptr, SourceLocation(), /*S=*/nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceRange TopLevelStmtDecl::getSourceRange() const {
|
|
|
|
return SourceRange(getLocation(), Statement->getEndLoc());
|
|
|
|
}
|
|
|
|
|
2013-02-22 17:15:32 +00:00
|
|
|
void EmptyDecl::anchor() {}
|
|
|
|
|
|
|
|
EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
|
2013-11-22 09:01:48 +00:00
|
|
|
return new (C, DC) EmptyDecl(DC, L);
|
2013-02-22 17:15:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2014-05-12 05:36:57 +00:00
|
|
|
return new (C, ID) EmptyDecl(nullptr, SourceLocation());
|
2013-02-22 17:15:32 +00:00
|
|
|
}
|
|
|
|
|
2022-07-15 17:45:57 +00:00
|
|
|
HLSLBufferDecl::HLSLBufferDecl(DeclContext *DC, bool CBuffer,
|
|
|
|
SourceLocation KwLoc, IdentifierInfo *ID,
|
|
|
|
SourceLocation IDLoc, SourceLocation LBrace)
|
|
|
|
: NamedDecl(Decl::Kind::HLSLBuffer, DC, IDLoc, DeclarationName(ID)),
|
|
|
|
DeclContext(Decl::Kind::HLSLBuffer), LBraceLoc(LBrace), KwLoc(KwLoc),
|
|
|
|
IsCBuffer(CBuffer) {}
|
|
|
|
|
|
|
|
HLSLBufferDecl *HLSLBufferDecl::Create(ASTContext &C,
|
|
|
|
DeclContext *LexicalParent, bool CBuffer,
|
|
|
|
SourceLocation KwLoc, IdentifierInfo *ID,
|
|
|
|
SourceLocation IDLoc,
|
|
|
|
SourceLocation LBrace) {
|
|
|
|
// For hlsl like this
|
|
|
|
// cbuffer A {
|
|
|
|
// cbuffer B {
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// compiler should treat it as
|
|
|
|
// cbuffer A {
|
|
|
|
// }
|
|
|
|
// cbuffer B {
|
|
|
|
// }
|
|
|
|
// FIXME: support nested buffers if required for back-compat.
|
|
|
|
DeclContext *DC = LexicalParent;
|
|
|
|
HLSLBufferDecl *Result =
|
|
|
|
new (C, DC) HLSLBufferDecl(DC, CBuffer, KwLoc, ID, IDLoc, LBrace);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
HLSLBufferDecl *HLSLBufferDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
|
|
|
return new (C, ID) HLSLBufferDecl(nullptr, false, SourceLocation(), nullptr,
|
|
|
|
SourceLocation(), SourceLocation());
|
|
|
|
}
|
|
|
|
|
2011-12-02 23:23:56 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ImportDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Retrieve the number of module identifiers needed to name the given
|
2011-12-02 23:23:56 +00:00
|
|
|
/// module.
|
|
|
|
static unsigned getNumModuleIdentifiers(Module *Mod) {
|
|
|
|
unsigned Result = 1;
|
|
|
|
while (Mod->Parent) {
|
|
|
|
Mod = Mod->Parent;
|
|
|
|
++Result;
|
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2018-07-30 19:24:48 +00:00
|
|
|
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
|
2011-12-02 23:23:56 +00:00
|
|
|
Module *Imported,
|
|
|
|
ArrayRef<SourceLocation> IdentifierLocs)
|
2020-02-28 02:13:54 +00:00
|
|
|
: Decl(Import, DC, StartLoc), ImportedModule(Imported),
|
|
|
|
NextLocalImportAndComplete(nullptr, true) {
|
2011-12-02 23:23:56 +00:00
|
|
|
assert(getNumModuleIdentifiers(Imported) == IdentifierLocs.size());
|
2015-11-09 17:53:06 +00:00
|
|
|
auto *StoredLocs = getTrailingObjects<SourceLocation>();
|
2015-08-06 20:26:32 +00:00
|
|
|
std::uninitialized_copy(IdentifierLocs.begin(), IdentifierLocs.end(),
|
|
|
|
StoredLocs);
|
2011-12-02 23:23:56 +00:00
|
|
|
}
|
|
|
|
|
2018-07-30 19:24:48 +00:00
|
|
|
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
|
2011-12-02 23:23:56 +00:00
|
|
|
Module *Imported, SourceLocation EndLoc)
|
2020-02-28 02:13:54 +00:00
|
|
|
: Decl(Import, DC, StartLoc), ImportedModule(Imported),
|
|
|
|
NextLocalImportAndComplete(nullptr, false) {
|
2015-08-06 20:26:32 +00:00
|
|
|
*getTrailingObjects<SourceLocation>() = EndLoc;
|
2011-12-02 23:23:56 +00:00
|
|
|
}
|
|
|
|
|
2013-11-22 09:01:48 +00:00
|
|
|
ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC,
|
2012-01-03 18:04:46 +00:00
|
|
|
SourceLocation StartLoc, Module *Imported,
|
2011-12-02 23:23:56 +00:00
|
|
|
ArrayRef<SourceLocation> IdentifierLocs) {
|
2015-08-06 20:26:32 +00:00
|
|
|
return new (C, DC,
|
|
|
|
additionalSizeToAlloc<SourceLocation>(IdentifierLocs.size()))
|
2013-11-22 09:01:48 +00:00
|
|
|
ImportDecl(DC, StartLoc, Imported, IdentifierLocs);
|
2011-12-02 23:23:56 +00:00
|
|
|
}
|
|
|
|
|
2013-11-22 09:01:48 +00:00
|
|
|
ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC,
|
2012-01-03 18:04:46 +00:00
|
|
|
SourceLocation StartLoc,
|
2013-11-22 09:01:48 +00:00
|
|
|
Module *Imported,
|
2011-12-02 23:23:56 +00:00
|
|
|
SourceLocation EndLoc) {
|
2015-08-06 20:26:32 +00:00
|
|
|
ImportDecl *Import = new (C, DC, additionalSizeToAlloc<SourceLocation>(1))
|
|
|
|
ImportDecl(DC, StartLoc, Imported, EndLoc);
|
2011-12-02 23:23:56 +00:00
|
|
|
Import->setImplicit();
|
|
|
|
return Import;
|
|
|
|
}
|
|
|
|
|
2012-01-05 21:55:30 +00:00
|
|
|
ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID,
|
|
|
|
unsigned NumLocations) {
|
2015-08-06 20:26:32 +00:00
|
|
|
return new (C, ID, additionalSizeToAlloc<SourceLocation>(NumLocations))
|
2013-11-22 09:01:48 +00:00
|
|
|
ImportDecl(EmptyShell());
|
2011-12-02 23:23:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const {
|
2020-02-28 02:13:54 +00:00
|
|
|
if (!isImportComplete())
|
2022-12-03 19:13:41 +00:00
|
|
|
return std::nullopt;
|
2011-12-02 23:23:56 +00:00
|
|
|
|
2015-11-09 17:53:06 +00:00
|
|
|
const auto *StoredLocs = getTrailingObjects<SourceLocation>();
|
2023-01-06 15:56:23 +00:00
|
|
|
return llvm::ArrayRef(StoredLocs,
|
|
|
|
getNumModuleIdentifiers(getImportedModule()));
|
2011-12-02 23:23:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SourceRange ImportDecl::getSourceRange() const {
|
2020-02-28 02:13:54 +00:00
|
|
|
if (!isImportComplete())
|
2015-08-06 20:26:32 +00:00
|
|
|
return SourceRange(getLocation(), *getTrailingObjects<SourceLocation>());
|
|
|
|
|
2011-12-02 23:23:56 +00:00
|
|
|
return SourceRange(getLocation(), getIdentifierLocs().back());
|
|
|
|
}
|
2016-09-08 23:14:54 +00:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ExportDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void ExportDecl::anchor() {}
|
|
|
|
|
|
|
|
ExportDecl *ExportDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation ExportLoc) {
|
|
|
|
return new (C, DC) ExportDecl(DC, ExportLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
|
|
|
return new (C, ID) ExportDecl(nullptr, SourceLocation());
|
|
|
|
}
|