1e5dd7070Spatrick //===- Decl.cpp - Declaration AST Node Implementation ---------------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements the Decl subclasses.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick
13e5dd7070Spatrick #include "clang/AST/Decl.h"
14e5dd7070Spatrick #include "Linkage.h"
15e5dd7070Spatrick #include "clang/AST/ASTContext.h"
16e5dd7070Spatrick #include "clang/AST/ASTDiagnostic.h"
17e5dd7070Spatrick #include "clang/AST/ASTLambda.h"
18e5dd7070Spatrick #include "clang/AST/ASTMutationListener.h"
19e5dd7070Spatrick #include "clang/AST/Attr.h"
20e5dd7070Spatrick #include "clang/AST/CanonicalType.h"
21e5dd7070Spatrick #include "clang/AST/DeclBase.h"
22e5dd7070Spatrick #include "clang/AST/DeclCXX.h"
23e5dd7070Spatrick #include "clang/AST/DeclObjC.h"
24e5dd7070Spatrick #include "clang/AST/DeclOpenMP.h"
25e5dd7070Spatrick #include "clang/AST/DeclTemplate.h"
26e5dd7070Spatrick #include "clang/AST/DeclarationName.h"
27e5dd7070Spatrick #include "clang/AST/Expr.h"
28e5dd7070Spatrick #include "clang/AST/ExprCXX.h"
29e5dd7070Spatrick #include "clang/AST/ExternalASTSource.h"
30e5dd7070Spatrick #include "clang/AST/ODRHash.h"
31e5dd7070Spatrick #include "clang/AST/PrettyDeclStackTrace.h"
32e5dd7070Spatrick #include "clang/AST/PrettyPrinter.h"
33*12c85518Srobert #include "clang/AST/Randstruct.h"
34*12c85518Srobert #include "clang/AST/RecordLayout.h"
35e5dd7070Spatrick #include "clang/AST/Redeclarable.h"
36e5dd7070Spatrick #include "clang/AST/Stmt.h"
37e5dd7070Spatrick #include "clang/AST/TemplateBase.h"
38e5dd7070Spatrick #include "clang/AST/Type.h"
39e5dd7070Spatrick #include "clang/AST/TypeLoc.h"
40e5dd7070Spatrick #include "clang/Basic/Builtins.h"
41e5dd7070Spatrick #include "clang/Basic/IdentifierTable.h"
42e5dd7070Spatrick #include "clang/Basic/LLVM.h"
43e5dd7070Spatrick #include "clang/Basic/LangOptions.h"
44e5dd7070Spatrick #include "clang/Basic/Linkage.h"
45e5dd7070Spatrick #include "clang/Basic/Module.h"
46a9ac8606Spatrick #include "clang/Basic/NoSanitizeList.h"
47e5dd7070Spatrick #include "clang/Basic/PartialDiagnostic.h"
48e5dd7070Spatrick #include "clang/Basic/Sanitizers.h"
49e5dd7070Spatrick #include "clang/Basic/SourceLocation.h"
50e5dd7070Spatrick #include "clang/Basic/SourceManager.h"
51e5dd7070Spatrick #include "clang/Basic/Specifiers.h"
52e5dd7070Spatrick #include "clang/Basic/TargetCXXABI.h"
53e5dd7070Spatrick #include "clang/Basic/TargetInfo.h"
54e5dd7070Spatrick #include "clang/Basic/Visibility.h"
55e5dd7070Spatrick #include "llvm/ADT/APSInt.h"
56e5dd7070Spatrick #include "llvm/ADT/ArrayRef.h"
57e5dd7070Spatrick #include "llvm/ADT/STLExtras.h"
58e5dd7070Spatrick #include "llvm/ADT/SmallVector.h"
59e5dd7070Spatrick #include "llvm/ADT/StringRef.h"
60e5dd7070Spatrick #include "llvm/ADT/StringSwitch.h"
61e5dd7070Spatrick #include "llvm/ADT/Triple.h"
62e5dd7070Spatrick #include "llvm/Support/Casting.h"
63e5dd7070Spatrick #include "llvm/Support/ErrorHandling.h"
64e5dd7070Spatrick #include "llvm/Support/raw_ostream.h"
65e5dd7070Spatrick #include <algorithm>
66e5dd7070Spatrick #include <cassert>
67e5dd7070Spatrick #include <cstddef>
68e5dd7070Spatrick #include <cstring>
69e5dd7070Spatrick #include <memory>
70*12c85518Srobert #include <optional>
71e5dd7070Spatrick #include <string>
72e5dd7070Spatrick #include <tuple>
73e5dd7070Spatrick #include <type_traits>
74e5dd7070Spatrick
75e5dd7070Spatrick using namespace clang;
76e5dd7070Spatrick
getPrimaryMergedDecl(Decl * D)77e5dd7070Spatrick Decl *clang::getPrimaryMergedDecl(Decl *D) {
78e5dd7070Spatrick return D->getASTContext().getPrimaryMergedDecl(D);
79e5dd7070Spatrick }
80e5dd7070Spatrick
print(raw_ostream & OS) const81e5dd7070Spatrick void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
82e5dd7070Spatrick SourceLocation Loc = this->Loc;
83e5dd7070Spatrick if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
84e5dd7070Spatrick if (Loc.isValid()) {
85e5dd7070Spatrick Loc.print(OS, Context.getSourceManager());
86e5dd7070Spatrick OS << ": ";
87e5dd7070Spatrick }
88e5dd7070Spatrick OS << Message;
89e5dd7070Spatrick
90e5dd7070Spatrick if (auto *ND = dyn_cast_or_null<NamedDecl>(TheDecl)) {
91e5dd7070Spatrick OS << " '";
92e5dd7070Spatrick ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true);
93e5dd7070Spatrick OS << "'";
94e5dd7070Spatrick }
95e5dd7070Spatrick
96e5dd7070Spatrick OS << '\n';
97e5dd7070Spatrick }
98e5dd7070Spatrick
99e5dd7070Spatrick // Defined here so that it can be inlined into its direct callers.
isOutOfLine() const100e5dd7070Spatrick bool Decl::isOutOfLine() const {
101e5dd7070Spatrick return !getLexicalDeclContext()->Equals(getDeclContext());
102e5dd7070Spatrick }
103e5dd7070Spatrick
TranslationUnitDecl(ASTContext & ctx)104e5dd7070Spatrick TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx)
105e5dd7070Spatrick : Decl(TranslationUnit, nullptr, SourceLocation()),
106a9ac8606Spatrick DeclContext(TranslationUnit), redeclarable_base(ctx), Ctx(ctx) {}
107e5dd7070Spatrick
108e5dd7070Spatrick //===----------------------------------------------------------------------===//
109e5dd7070Spatrick // NamedDecl Implementation
110e5dd7070Spatrick //===----------------------------------------------------------------------===//
111e5dd7070Spatrick
112e5dd7070Spatrick // Visibility rules aren't rigorously externally specified, but here
113e5dd7070Spatrick // are the basic principles behind what we implement:
114e5dd7070Spatrick //
115e5dd7070Spatrick // 1. An explicit visibility attribute is generally a direct expression
116e5dd7070Spatrick // of the user's intent and should be honored. Only the innermost
117e5dd7070Spatrick // visibility attribute applies. If no visibility attribute applies,
118e5dd7070Spatrick // global visibility settings are considered.
119e5dd7070Spatrick //
120e5dd7070Spatrick // 2. There is one caveat to the above: on or in a template pattern,
121e5dd7070Spatrick // an explicit visibility attribute is just a default rule, and
122e5dd7070Spatrick // visibility can be decreased by the visibility of template
123e5dd7070Spatrick // arguments. But this, too, has an exception: an attribute on an
124e5dd7070Spatrick // explicit specialization or instantiation causes all the visibility
125e5dd7070Spatrick // restrictions of the template arguments to be ignored.
126e5dd7070Spatrick //
127e5dd7070Spatrick // 3. A variable that does not otherwise have explicit visibility can
128e5dd7070Spatrick // be restricted by the visibility of its type.
129e5dd7070Spatrick //
130e5dd7070Spatrick // 4. A visibility restriction is explicit if it comes from an
131e5dd7070Spatrick // attribute (or something like it), not a global visibility setting.
132e5dd7070Spatrick // When emitting a reference to an external symbol, visibility
133e5dd7070Spatrick // restrictions are ignored unless they are explicit.
134e5dd7070Spatrick //
135e5dd7070Spatrick // 5. When computing the visibility of a non-type, including a
136e5dd7070Spatrick // non-type member of a class, only non-type visibility restrictions
137e5dd7070Spatrick // are considered: the 'visibility' attribute, global value-visibility
138e5dd7070Spatrick // settings, and a few special cases like __private_extern.
139e5dd7070Spatrick //
140e5dd7070Spatrick // 6. When computing the visibility of a type, including a type member
141e5dd7070Spatrick // of a class, only type visibility restrictions are considered:
142e5dd7070Spatrick // the 'type_visibility' attribute and global type-visibility settings.
143e5dd7070Spatrick // However, a 'visibility' attribute counts as a 'type_visibility'
144e5dd7070Spatrick // attribute on any declaration that only has the former.
145e5dd7070Spatrick //
146e5dd7070Spatrick // The visibility of a "secondary" entity, like a template argument,
147e5dd7070Spatrick // is computed using the kind of that entity, not the kind of the
148e5dd7070Spatrick // primary entity for which we are computing visibility. For example,
149e5dd7070Spatrick // the visibility of a specialization of either of these templates:
150e5dd7070Spatrick // template <class T, bool (&compare)(T, X)> bool has_match(list<T>, X);
151e5dd7070Spatrick // template <class T, bool (&compare)(T, X)> class matcher;
152e5dd7070Spatrick // is restricted according to the type visibility of the argument 'T',
153e5dd7070Spatrick // the type visibility of 'bool(&)(T,X)', and the value visibility of
154e5dd7070Spatrick // the argument function 'compare'. That 'has_match' is a value
155e5dd7070Spatrick // and 'matcher' is a type only matters when looking for attributes
156e5dd7070Spatrick // and settings from the immediate context.
157e5dd7070Spatrick
158e5dd7070Spatrick /// Does this computation kind permit us to consider additional
159e5dd7070Spatrick /// visibility settings from attributes and the like?
hasExplicitVisibilityAlready(LVComputationKind computation)160e5dd7070Spatrick static bool hasExplicitVisibilityAlready(LVComputationKind computation) {
161e5dd7070Spatrick return computation.IgnoreExplicitVisibility;
162e5dd7070Spatrick }
163e5dd7070Spatrick
164e5dd7070Spatrick /// Given an LVComputationKind, return one of the same type/value sort
165e5dd7070Spatrick /// that records that it already has explicit visibility.
166e5dd7070Spatrick static LVComputationKind
withExplicitVisibilityAlready(LVComputationKind Kind)167e5dd7070Spatrick withExplicitVisibilityAlready(LVComputationKind Kind) {
168e5dd7070Spatrick Kind.IgnoreExplicitVisibility = true;
169e5dd7070Spatrick return Kind;
170e5dd7070Spatrick }
171e5dd7070Spatrick
getExplicitVisibility(const NamedDecl * D,LVComputationKind kind)172*12c85518Srobert static std::optional<Visibility> getExplicitVisibility(const NamedDecl *D,
173e5dd7070Spatrick LVComputationKind kind) {
174e5dd7070Spatrick assert(!kind.IgnoreExplicitVisibility &&
175e5dd7070Spatrick "asking for explicit visibility when we shouldn't be");
176e5dd7070Spatrick return D->getExplicitVisibility(kind.getExplicitVisibilityKind());
177e5dd7070Spatrick }
178e5dd7070Spatrick
179e5dd7070Spatrick /// Is the given declaration a "type" or a "value" for the purposes of
180e5dd7070Spatrick /// visibility computation?
usesTypeVisibility(const NamedDecl * D)181e5dd7070Spatrick static bool usesTypeVisibility(const NamedDecl *D) {
182e5dd7070Spatrick return isa<TypeDecl>(D) ||
183e5dd7070Spatrick isa<ClassTemplateDecl>(D) ||
184e5dd7070Spatrick isa<ObjCInterfaceDecl>(D);
185e5dd7070Spatrick }
186e5dd7070Spatrick
187e5dd7070Spatrick /// Does the given declaration have member specialization information,
188e5dd7070Spatrick /// and if so, is it an explicit specialization?
189*12c85518Srobert template <class T>
190*12c85518Srobert static std::enable_if_t<!std::is_base_of_v<RedeclarableTemplateDecl, T>, bool>
isExplicitMemberSpecialization(const T * D)191e5dd7070Spatrick isExplicitMemberSpecialization(const T *D) {
192e5dd7070Spatrick if (const MemberSpecializationInfo *member =
193e5dd7070Spatrick D->getMemberSpecializationInfo()) {
194e5dd7070Spatrick return member->isExplicitSpecialization();
195e5dd7070Spatrick }
196e5dd7070Spatrick return false;
197e5dd7070Spatrick }
198e5dd7070Spatrick
199e5dd7070Spatrick /// For templates, this question is easier: a member template can't be
200e5dd7070Spatrick /// explicitly instantiated, so there's a single bit indicating whether
201e5dd7070Spatrick /// or not this is an explicit member specialization.
isExplicitMemberSpecialization(const RedeclarableTemplateDecl * D)202e5dd7070Spatrick static bool isExplicitMemberSpecialization(const RedeclarableTemplateDecl *D) {
203e5dd7070Spatrick return D->isMemberSpecialization();
204e5dd7070Spatrick }
205e5dd7070Spatrick
206e5dd7070Spatrick /// Given a visibility attribute, return the explicit visibility
207e5dd7070Spatrick /// associated with it.
208e5dd7070Spatrick template <class T>
getVisibilityFromAttr(const T * attr)209e5dd7070Spatrick static Visibility getVisibilityFromAttr(const T *attr) {
210e5dd7070Spatrick switch (attr->getVisibility()) {
211e5dd7070Spatrick case T::Default:
212e5dd7070Spatrick return DefaultVisibility;
213e5dd7070Spatrick case T::Hidden:
214e5dd7070Spatrick return HiddenVisibility;
215e5dd7070Spatrick case T::Protected:
216e5dd7070Spatrick return ProtectedVisibility;
217e5dd7070Spatrick }
218e5dd7070Spatrick llvm_unreachable("bad visibility kind");
219e5dd7070Spatrick }
220e5dd7070Spatrick
221e5dd7070Spatrick /// Return the explicit visibility of the given declaration.
222*12c85518Srobert static std::optional<Visibility>
getVisibilityOf(const NamedDecl * D,NamedDecl::ExplicitVisibilityKind kind)223*12c85518Srobert getVisibilityOf(const NamedDecl *D, NamedDecl::ExplicitVisibilityKind kind) {
224e5dd7070Spatrick // If we're ultimately computing the visibility of a type, look for
225e5dd7070Spatrick // a 'type_visibility' attribute before looking for 'visibility'.
226e5dd7070Spatrick if (kind == NamedDecl::VisibilityForType) {
227e5dd7070Spatrick if (const auto *A = D->getAttr<TypeVisibilityAttr>()) {
228e5dd7070Spatrick return getVisibilityFromAttr(A);
229e5dd7070Spatrick }
230e5dd7070Spatrick }
231e5dd7070Spatrick
232e5dd7070Spatrick // If this declaration has an explicit visibility attribute, use it.
233e5dd7070Spatrick if (const auto *A = D->getAttr<VisibilityAttr>()) {
234e5dd7070Spatrick return getVisibilityFromAttr(A);
235e5dd7070Spatrick }
236e5dd7070Spatrick
237*12c85518Srobert return std::nullopt;
238e5dd7070Spatrick }
239e5dd7070Spatrick
getLVForType(const Type & T,LVComputationKind computation)240e5dd7070Spatrick LinkageInfo LinkageComputer::getLVForType(const Type &T,
241e5dd7070Spatrick LVComputationKind computation) {
242e5dd7070Spatrick if (computation.IgnoreAllVisibility)
243e5dd7070Spatrick return LinkageInfo(T.getLinkage(), DefaultVisibility, true);
244e5dd7070Spatrick return getTypeLinkageAndVisibility(&T);
245e5dd7070Spatrick }
246e5dd7070Spatrick
247e5dd7070Spatrick /// Get the most restrictive linkage for the types in the given
248e5dd7070Spatrick /// template parameter list. For visibility purposes, template
249e5dd7070Spatrick /// parameters are part of the signature of a template.
getLVForTemplateParameterList(const TemplateParameterList * Params,LVComputationKind computation)250e5dd7070Spatrick LinkageInfo LinkageComputer::getLVForTemplateParameterList(
251e5dd7070Spatrick const TemplateParameterList *Params, LVComputationKind computation) {
252e5dd7070Spatrick LinkageInfo LV;
253e5dd7070Spatrick for (const NamedDecl *P : *Params) {
254e5dd7070Spatrick // Template type parameters are the most common and never
255e5dd7070Spatrick // contribute to visibility, pack or not.
256e5dd7070Spatrick if (isa<TemplateTypeParmDecl>(P))
257e5dd7070Spatrick continue;
258e5dd7070Spatrick
259e5dd7070Spatrick // Non-type template parameters can be restricted by the value type, e.g.
260e5dd7070Spatrick // template <enum X> class A { ... };
261e5dd7070Spatrick // We have to be careful here, though, because we can be dealing with
262e5dd7070Spatrick // dependent types.
263e5dd7070Spatrick if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
264e5dd7070Spatrick // Handle the non-pack case first.
265e5dd7070Spatrick if (!NTTP->isExpandedParameterPack()) {
266e5dd7070Spatrick if (!NTTP->getType()->isDependentType()) {
267e5dd7070Spatrick LV.merge(getLVForType(*NTTP->getType(), computation));
268e5dd7070Spatrick }
269e5dd7070Spatrick continue;
270e5dd7070Spatrick }
271e5dd7070Spatrick
272e5dd7070Spatrick // Look at all the types in an expanded pack.
273e5dd7070Spatrick for (unsigned i = 0, n = NTTP->getNumExpansionTypes(); i != n; ++i) {
274e5dd7070Spatrick QualType type = NTTP->getExpansionType(i);
275e5dd7070Spatrick if (!type->isDependentType())
276e5dd7070Spatrick LV.merge(getTypeLinkageAndVisibility(type));
277e5dd7070Spatrick }
278e5dd7070Spatrick continue;
279e5dd7070Spatrick }
280e5dd7070Spatrick
281e5dd7070Spatrick // Template template parameters can be restricted by their
282e5dd7070Spatrick // template parameters, recursively.
283e5dd7070Spatrick const auto *TTP = cast<TemplateTemplateParmDecl>(P);
284e5dd7070Spatrick
285e5dd7070Spatrick // Handle the non-pack case first.
286e5dd7070Spatrick if (!TTP->isExpandedParameterPack()) {
287e5dd7070Spatrick LV.merge(getLVForTemplateParameterList(TTP->getTemplateParameters(),
288e5dd7070Spatrick computation));
289e5dd7070Spatrick continue;
290e5dd7070Spatrick }
291e5dd7070Spatrick
292e5dd7070Spatrick // Look at all expansions in an expanded pack.
293e5dd7070Spatrick for (unsigned i = 0, n = TTP->getNumExpansionTemplateParameters();
294e5dd7070Spatrick i != n; ++i) {
295e5dd7070Spatrick LV.merge(getLVForTemplateParameterList(
296e5dd7070Spatrick TTP->getExpansionTemplateParameters(i), computation));
297e5dd7070Spatrick }
298e5dd7070Spatrick }
299e5dd7070Spatrick
300e5dd7070Spatrick return LV;
301e5dd7070Spatrick }
302e5dd7070Spatrick
getOutermostFuncOrBlockContext(const Decl * D)303e5dd7070Spatrick static const Decl *getOutermostFuncOrBlockContext(const Decl *D) {
304e5dd7070Spatrick const Decl *Ret = nullptr;
305e5dd7070Spatrick const DeclContext *DC = D->getDeclContext();
306e5dd7070Spatrick while (DC->getDeclKind() != Decl::TranslationUnit) {
307e5dd7070Spatrick if (isa<FunctionDecl>(DC) || isa<BlockDecl>(DC))
308e5dd7070Spatrick Ret = cast<Decl>(DC);
309e5dd7070Spatrick DC = DC->getParent();
310e5dd7070Spatrick }
311e5dd7070Spatrick return Ret;
312e5dd7070Spatrick }
313e5dd7070Spatrick
314e5dd7070Spatrick /// Get the most restrictive linkage for the types and
315e5dd7070Spatrick /// declarations in the given template argument list.
316e5dd7070Spatrick ///
317e5dd7070Spatrick /// Note that we don't take an LVComputationKind because we always
318e5dd7070Spatrick /// want to honor the visibility of template arguments in the same way.
319e5dd7070Spatrick LinkageInfo
getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,LVComputationKind computation)320e5dd7070Spatrick LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
321e5dd7070Spatrick LVComputationKind computation) {
322e5dd7070Spatrick LinkageInfo LV;
323e5dd7070Spatrick
324e5dd7070Spatrick for (const TemplateArgument &Arg : Args) {
325e5dd7070Spatrick switch (Arg.getKind()) {
326e5dd7070Spatrick case TemplateArgument::Null:
327e5dd7070Spatrick case TemplateArgument::Integral:
328e5dd7070Spatrick case TemplateArgument::Expression:
329e5dd7070Spatrick continue;
330e5dd7070Spatrick
331e5dd7070Spatrick case TemplateArgument::Type:
332e5dd7070Spatrick LV.merge(getLVForType(*Arg.getAsType(), computation));
333e5dd7070Spatrick continue;
334e5dd7070Spatrick
335e5dd7070Spatrick case TemplateArgument::Declaration: {
336e5dd7070Spatrick const NamedDecl *ND = Arg.getAsDecl();
337e5dd7070Spatrick assert(!usesTypeVisibility(ND));
338e5dd7070Spatrick LV.merge(getLVForDecl(ND, computation));
339e5dd7070Spatrick continue;
340e5dd7070Spatrick }
341e5dd7070Spatrick
342e5dd7070Spatrick case TemplateArgument::NullPtr:
343e5dd7070Spatrick LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType()));
344e5dd7070Spatrick continue;
345e5dd7070Spatrick
346e5dd7070Spatrick case TemplateArgument::Template:
347e5dd7070Spatrick case TemplateArgument::TemplateExpansion:
348e5dd7070Spatrick if (TemplateDecl *Template =
349e5dd7070Spatrick Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
350e5dd7070Spatrick LV.merge(getLVForDecl(Template, computation));
351e5dd7070Spatrick continue;
352e5dd7070Spatrick
353e5dd7070Spatrick case TemplateArgument::Pack:
354e5dd7070Spatrick LV.merge(getLVForTemplateArgumentList(Arg.getPackAsArray(), computation));
355e5dd7070Spatrick continue;
356e5dd7070Spatrick }
357e5dd7070Spatrick llvm_unreachable("bad template argument kind");
358e5dd7070Spatrick }
359e5dd7070Spatrick
360e5dd7070Spatrick return LV;
361e5dd7070Spatrick }
362e5dd7070Spatrick
363e5dd7070Spatrick LinkageInfo
getLVForTemplateArgumentList(const TemplateArgumentList & TArgs,LVComputationKind computation)364e5dd7070Spatrick LinkageComputer::getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
365e5dd7070Spatrick LVComputationKind computation) {
366e5dd7070Spatrick return getLVForTemplateArgumentList(TArgs.asArray(), computation);
367e5dd7070Spatrick }
368e5dd7070Spatrick
shouldConsiderTemplateVisibility(const FunctionDecl * fn,const FunctionTemplateSpecializationInfo * specInfo)369e5dd7070Spatrick static bool shouldConsiderTemplateVisibility(const FunctionDecl *fn,
370e5dd7070Spatrick const FunctionTemplateSpecializationInfo *specInfo) {
371e5dd7070Spatrick // Include visibility from the template parameters and arguments
372e5dd7070Spatrick // only if this is not an explicit instantiation or specialization
373e5dd7070Spatrick // with direct explicit visibility. (Implicit instantiations won't
374e5dd7070Spatrick // have a direct attribute.)
375e5dd7070Spatrick if (!specInfo->isExplicitInstantiationOrSpecialization())
376e5dd7070Spatrick return true;
377e5dd7070Spatrick
378e5dd7070Spatrick return !fn->hasAttr<VisibilityAttr>();
379e5dd7070Spatrick }
380e5dd7070Spatrick
381e5dd7070Spatrick /// Merge in template-related linkage and visibility for the given
382e5dd7070Spatrick /// function template specialization.
383e5dd7070Spatrick ///
384e5dd7070Spatrick /// We don't need a computation kind here because we can assume
385e5dd7070Spatrick /// LVForValue.
386e5dd7070Spatrick ///
387e5dd7070Spatrick /// \param[out] LV the computation to use for the parent
mergeTemplateLV(LinkageInfo & LV,const FunctionDecl * fn,const FunctionTemplateSpecializationInfo * specInfo,LVComputationKind computation)388e5dd7070Spatrick void LinkageComputer::mergeTemplateLV(
389e5dd7070Spatrick LinkageInfo &LV, const FunctionDecl *fn,
390e5dd7070Spatrick const FunctionTemplateSpecializationInfo *specInfo,
391e5dd7070Spatrick LVComputationKind computation) {
392e5dd7070Spatrick bool considerVisibility =
393e5dd7070Spatrick shouldConsiderTemplateVisibility(fn, specInfo);
394e5dd7070Spatrick
395e5dd7070Spatrick FunctionTemplateDecl *temp = specInfo->getTemplate();
396*12c85518Srobert // Merge information from the template declaration.
397*12c85518Srobert LinkageInfo tempLV = getLVForDecl(temp, computation);
398*12c85518Srobert // The linkage of the specialization should be consistent with the
399*12c85518Srobert // template declaration.
400*12c85518Srobert LV.setLinkage(tempLV.getLinkage());
401*12c85518Srobert
402*12c85518Srobert // Merge information from the template parameters.
403*12c85518Srobert LinkageInfo paramsLV =
404e5dd7070Spatrick getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
405*12c85518Srobert LV.mergeMaybeWithVisibility(paramsLV, considerVisibility);
406e5dd7070Spatrick
407e5dd7070Spatrick // Merge information from the template arguments.
408e5dd7070Spatrick const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments;
409e5dd7070Spatrick LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
410e5dd7070Spatrick LV.mergeMaybeWithVisibility(argsLV, considerVisibility);
411e5dd7070Spatrick }
412e5dd7070Spatrick
413e5dd7070Spatrick /// Does the given declaration have a direct visibility attribute
414e5dd7070Spatrick /// that would match the given rules?
hasDirectVisibilityAttribute(const NamedDecl * D,LVComputationKind computation)415e5dd7070Spatrick static bool hasDirectVisibilityAttribute(const NamedDecl *D,
416e5dd7070Spatrick LVComputationKind computation) {
417e5dd7070Spatrick if (computation.IgnoreAllVisibility)
418e5dd7070Spatrick return false;
419e5dd7070Spatrick
420e5dd7070Spatrick return (computation.isTypeVisibility() && D->hasAttr<TypeVisibilityAttr>()) ||
421e5dd7070Spatrick D->hasAttr<VisibilityAttr>();
422e5dd7070Spatrick }
423e5dd7070Spatrick
424e5dd7070Spatrick /// Should we consider visibility associated with the template
425e5dd7070Spatrick /// arguments and parameters of the given class template specialization?
shouldConsiderTemplateVisibility(const ClassTemplateSpecializationDecl * spec,LVComputationKind computation)426e5dd7070Spatrick static bool shouldConsiderTemplateVisibility(
427e5dd7070Spatrick const ClassTemplateSpecializationDecl *spec,
428e5dd7070Spatrick LVComputationKind computation) {
429e5dd7070Spatrick // Include visibility from the template parameters and arguments
430e5dd7070Spatrick // only if this is not an explicit instantiation or specialization
431e5dd7070Spatrick // with direct explicit visibility (and note that implicit
432e5dd7070Spatrick // instantiations won't have a direct attribute).
433e5dd7070Spatrick //
434e5dd7070Spatrick // Furthermore, we want to ignore template parameters and arguments
435e5dd7070Spatrick // for an explicit specialization when computing the visibility of a
436e5dd7070Spatrick // member thereof with explicit visibility.
437e5dd7070Spatrick //
438e5dd7070Spatrick // This is a bit complex; let's unpack it.
439e5dd7070Spatrick //
440e5dd7070Spatrick // An explicit class specialization is an independent, top-level
441e5dd7070Spatrick // declaration. As such, if it or any of its members has an
442e5dd7070Spatrick // explicit visibility attribute, that must directly express the
443e5dd7070Spatrick // user's intent, and we should honor it. The same logic applies to
444e5dd7070Spatrick // an explicit instantiation of a member of such a thing.
445e5dd7070Spatrick
446e5dd7070Spatrick // Fast path: if this is not an explicit instantiation or
447e5dd7070Spatrick // specialization, we always want to consider template-related
448e5dd7070Spatrick // visibility restrictions.
449e5dd7070Spatrick if (!spec->isExplicitInstantiationOrSpecialization())
450e5dd7070Spatrick return true;
451e5dd7070Spatrick
452e5dd7070Spatrick // This is the 'member thereof' check.
453e5dd7070Spatrick if (spec->isExplicitSpecialization() &&
454e5dd7070Spatrick hasExplicitVisibilityAlready(computation))
455e5dd7070Spatrick return false;
456e5dd7070Spatrick
457e5dd7070Spatrick return !hasDirectVisibilityAttribute(spec, computation);
458e5dd7070Spatrick }
459e5dd7070Spatrick
460e5dd7070Spatrick /// Merge in template-related linkage and visibility for the given
461e5dd7070Spatrick /// class template specialization.
mergeTemplateLV(LinkageInfo & LV,const ClassTemplateSpecializationDecl * spec,LVComputationKind computation)462e5dd7070Spatrick void LinkageComputer::mergeTemplateLV(
463e5dd7070Spatrick LinkageInfo &LV, const ClassTemplateSpecializationDecl *spec,
464e5dd7070Spatrick LVComputationKind computation) {
465e5dd7070Spatrick bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation);
466e5dd7070Spatrick
467e5dd7070Spatrick // Merge information from the template parameters, but ignore
468e5dd7070Spatrick // visibility if we're only considering template arguments.
469e5dd7070Spatrick ClassTemplateDecl *temp = spec->getSpecializedTemplate();
470*12c85518Srobert // Merge information from the template declaration.
471*12c85518Srobert LinkageInfo tempLV = getLVForDecl(temp, computation);
472*12c85518Srobert // The linkage of the specialization should be consistent with the
473*12c85518Srobert // template declaration.
474*12c85518Srobert LV.setLinkage(tempLV.getLinkage());
475*12c85518Srobert
476*12c85518Srobert LinkageInfo paramsLV =
477e5dd7070Spatrick getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
478*12c85518Srobert LV.mergeMaybeWithVisibility(paramsLV,
479e5dd7070Spatrick considerVisibility && !hasExplicitVisibilityAlready(computation));
480e5dd7070Spatrick
481e5dd7070Spatrick // Merge information from the template arguments. We ignore
482e5dd7070Spatrick // template-argument visibility if we've got an explicit
483e5dd7070Spatrick // instantiation with a visibility attribute.
484e5dd7070Spatrick const TemplateArgumentList &templateArgs = spec->getTemplateArgs();
485e5dd7070Spatrick LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
486e5dd7070Spatrick if (considerVisibility)
487e5dd7070Spatrick LV.mergeVisibility(argsLV);
488e5dd7070Spatrick LV.mergeExternalVisibility(argsLV);
489e5dd7070Spatrick }
490e5dd7070Spatrick
491e5dd7070Spatrick /// Should we consider visibility associated with the template
492e5dd7070Spatrick /// arguments and parameters of the given variable template
493e5dd7070Spatrick /// specialization? As usual, follow class template specialization
494e5dd7070Spatrick /// logic up to initialization.
shouldConsiderTemplateVisibility(const VarTemplateSpecializationDecl * spec,LVComputationKind computation)495e5dd7070Spatrick static bool shouldConsiderTemplateVisibility(
496e5dd7070Spatrick const VarTemplateSpecializationDecl *spec,
497e5dd7070Spatrick LVComputationKind computation) {
498e5dd7070Spatrick // Include visibility from the template parameters and arguments
499e5dd7070Spatrick // only if this is not an explicit instantiation or specialization
500e5dd7070Spatrick // with direct explicit visibility (and note that implicit
501e5dd7070Spatrick // instantiations won't have a direct attribute).
502e5dd7070Spatrick if (!spec->isExplicitInstantiationOrSpecialization())
503e5dd7070Spatrick return true;
504e5dd7070Spatrick
505e5dd7070Spatrick // An explicit variable specialization is an independent, top-level
506e5dd7070Spatrick // declaration. As such, if it has an explicit visibility attribute,
507e5dd7070Spatrick // that must directly express the user's intent, and we should honor
508e5dd7070Spatrick // it.
509e5dd7070Spatrick if (spec->isExplicitSpecialization() &&
510e5dd7070Spatrick hasExplicitVisibilityAlready(computation))
511e5dd7070Spatrick return false;
512e5dd7070Spatrick
513e5dd7070Spatrick return !hasDirectVisibilityAttribute(spec, computation);
514e5dd7070Spatrick }
515e5dd7070Spatrick
516e5dd7070Spatrick /// Merge in template-related linkage and visibility for the given
517e5dd7070Spatrick /// variable template specialization. As usual, follow class template
518e5dd7070Spatrick /// specialization logic up to initialization.
mergeTemplateLV(LinkageInfo & LV,const VarTemplateSpecializationDecl * spec,LVComputationKind computation)519e5dd7070Spatrick void LinkageComputer::mergeTemplateLV(LinkageInfo &LV,
520e5dd7070Spatrick const VarTemplateSpecializationDecl *spec,
521e5dd7070Spatrick LVComputationKind computation) {
522e5dd7070Spatrick bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation);
523e5dd7070Spatrick
524e5dd7070Spatrick // Merge information from the template parameters, but ignore
525e5dd7070Spatrick // visibility if we're only considering template arguments.
526e5dd7070Spatrick VarTemplateDecl *temp = spec->getSpecializedTemplate();
527e5dd7070Spatrick LinkageInfo tempLV =
528e5dd7070Spatrick getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
529e5dd7070Spatrick LV.mergeMaybeWithVisibility(tempLV,
530e5dd7070Spatrick considerVisibility && !hasExplicitVisibilityAlready(computation));
531e5dd7070Spatrick
532e5dd7070Spatrick // Merge information from the template arguments. We ignore
533e5dd7070Spatrick // template-argument visibility if we've got an explicit
534e5dd7070Spatrick // instantiation with a visibility attribute.
535e5dd7070Spatrick const TemplateArgumentList &templateArgs = spec->getTemplateArgs();
536e5dd7070Spatrick LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
537e5dd7070Spatrick if (considerVisibility)
538e5dd7070Spatrick LV.mergeVisibility(argsLV);
539e5dd7070Spatrick LV.mergeExternalVisibility(argsLV);
540e5dd7070Spatrick }
541e5dd7070Spatrick
useInlineVisibilityHidden(const NamedDecl * D)542e5dd7070Spatrick static bool useInlineVisibilityHidden(const NamedDecl *D) {
543e5dd7070Spatrick // FIXME: we should warn if -fvisibility-inlines-hidden is used with c.
544e5dd7070Spatrick const LangOptions &Opts = D->getASTContext().getLangOpts();
545e5dd7070Spatrick if (!Opts.CPlusPlus || !Opts.InlineVisibilityHidden)
546e5dd7070Spatrick return false;
547e5dd7070Spatrick
548e5dd7070Spatrick const auto *FD = dyn_cast<FunctionDecl>(D);
549e5dd7070Spatrick if (!FD)
550e5dd7070Spatrick return false;
551e5dd7070Spatrick
552e5dd7070Spatrick TemplateSpecializationKind TSK = TSK_Undeclared;
553e5dd7070Spatrick if (FunctionTemplateSpecializationInfo *spec
554e5dd7070Spatrick = FD->getTemplateSpecializationInfo()) {
555e5dd7070Spatrick TSK = spec->getTemplateSpecializationKind();
556e5dd7070Spatrick } else if (MemberSpecializationInfo *MSI =
557e5dd7070Spatrick FD->getMemberSpecializationInfo()) {
558e5dd7070Spatrick TSK = MSI->getTemplateSpecializationKind();
559e5dd7070Spatrick }
560e5dd7070Spatrick
561e5dd7070Spatrick const FunctionDecl *Def = nullptr;
562e5dd7070Spatrick // InlineVisibilityHidden only applies to definitions, and
563e5dd7070Spatrick // isInlined() only gives meaningful answers on definitions
564e5dd7070Spatrick // anyway.
565e5dd7070Spatrick return TSK != TSK_ExplicitInstantiationDeclaration &&
566e5dd7070Spatrick TSK != TSK_ExplicitInstantiationDefinition &&
567e5dd7070Spatrick FD->hasBody(Def) && Def->isInlined() && !Def->hasAttr<GNUInlineAttr>();
568e5dd7070Spatrick }
569e5dd7070Spatrick
isFirstInExternCContext(T * D)570e5dd7070Spatrick template <typename T> static bool isFirstInExternCContext(T *D) {
571e5dd7070Spatrick const T *First = D->getFirstDecl();
572e5dd7070Spatrick return First->isInExternCContext();
573e5dd7070Spatrick }
574e5dd7070Spatrick
isSingleLineLanguageLinkage(const Decl & D)575e5dd7070Spatrick static bool isSingleLineLanguageLinkage(const Decl &D) {
576e5dd7070Spatrick if (const auto *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext()))
577e5dd7070Spatrick if (!SD->hasBraces())
578e5dd7070Spatrick return true;
579e5dd7070Spatrick return false;
580e5dd7070Spatrick }
581e5dd7070Spatrick
582e5dd7070Spatrick /// Determine whether D is declared in the purview of a named module.
isInModulePurview(const NamedDecl * D)583e5dd7070Spatrick static bool isInModulePurview(const NamedDecl *D) {
584e5dd7070Spatrick if (auto *M = D->getOwningModule())
585e5dd7070Spatrick return M->isModulePurview();
586e5dd7070Spatrick return false;
587e5dd7070Spatrick }
588e5dd7070Spatrick
isExportedFromModuleInterfaceUnit(const NamedDecl * D)589e5dd7070Spatrick static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
590e5dd7070Spatrick // FIXME: Handle isModulePrivate.
591e5dd7070Spatrick switch (D->getModuleOwnershipKind()) {
592e5dd7070Spatrick case Decl::ModuleOwnershipKind::Unowned:
593*12c85518Srobert case Decl::ModuleOwnershipKind::ReachableWhenImported:
594e5dd7070Spatrick case Decl::ModuleOwnershipKind::ModulePrivate:
595e5dd7070Spatrick return false;
596e5dd7070Spatrick case Decl::ModuleOwnershipKind::Visible:
597e5dd7070Spatrick case Decl::ModuleOwnershipKind::VisibleWhenImported:
598e5dd7070Spatrick return isInModulePurview(D);
599e5dd7070Spatrick }
600e5dd7070Spatrick llvm_unreachable("unexpected module ownership kind");
601e5dd7070Spatrick }
602e5dd7070Spatrick
getInternalLinkageFor(const NamedDecl * D)603e5dd7070Spatrick static LinkageInfo getInternalLinkageFor(const NamedDecl *D) {
604*12c85518Srobert // (for the modules ts) Internal linkage declarations within a module
605*12c85518Srobert // interface unit are modeled as "module-internal linkage", which means that
606*12c85518Srobert // they have internal linkage formally but can be indirectly accessed from
607*12c85518Srobert // outside the module via inline functions and templates defined within the
608*12c85518Srobert // module.
609*12c85518Srobert if (isInModulePurview(D) && D->getASTContext().getLangOpts().ModulesTS)
610e5dd7070Spatrick return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false);
611e5dd7070Spatrick
612e5dd7070Spatrick return LinkageInfo::internal();
613e5dd7070Spatrick }
614e5dd7070Spatrick
getExternalLinkageFor(const NamedDecl * D)615e5dd7070Spatrick static LinkageInfo getExternalLinkageFor(const NamedDecl *D) {
616e5dd7070Spatrick // C++ Modules TS [basic.link]/6.8:
617e5dd7070Spatrick // - A name declared at namespace scope that does not have internal linkage
618e5dd7070Spatrick // by the previous rules and that is introduced by a non-exported
619e5dd7070Spatrick // declaration has module linkage.
620*12c85518Srobert //
621*12c85518Srobert // [basic.namespace.general]/p2
622*12c85518Srobert // A namespace is never attached to a named module and never has a name with
623*12c85518Srobert // module linkage.
624*12c85518Srobert if (isInModulePurview(D) &&
625*12c85518Srobert !isExportedFromModuleInterfaceUnit(
626*12c85518Srobert cast<NamedDecl>(D->getCanonicalDecl())) &&
627*12c85518Srobert !isa<NamespaceDecl>(D))
628e5dd7070Spatrick return LinkageInfo(ModuleLinkage, DefaultVisibility, false);
629e5dd7070Spatrick
630e5dd7070Spatrick return LinkageInfo::external();
631e5dd7070Spatrick }
632e5dd7070Spatrick
getStorageClass(const Decl * D)633e5dd7070Spatrick static StorageClass getStorageClass(const Decl *D) {
634e5dd7070Spatrick if (auto *TD = dyn_cast<TemplateDecl>(D))
635e5dd7070Spatrick D = TD->getTemplatedDecl();
636e5dd7070Spatrick if (D) {
637e5dd7070Spatrick if (auto *VD = dyn_cast<VarDecl>(D))
638e5dd7070Spatrick return VD->getStorageClass();
639e5dd7070Spatrick if (auto *FD = dyn_cast<FunctionDecl>(D))
640e5dd7070Spatrick return FD->getStorageClass();
641e5dd7070Spatrick }
642e5dd7070Spatrick return SC_None;
643e5dd7070Spatrick }
644e5dd7070Spatrick
645e5dd7070Spatrick LinkageInfo
getLVForNamespaceScopeDecl(const NamedDecl * D,LVComputationKind computation,bool IgnoreVarTypeLinkage)646e5dd7070Spatrick LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
647e5dd7070Spatrick LVComputationKind computation,
648e5dd7070Spatrick bool IgnoreVarTypeLinkage) {
649e5dd7070Spatrick assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
650e5dd7070Spatrick "Not a name having namespace scope");
651e5dd7070Spatrick ASTContext &Context = D->getASTContext();
652e5dd7070Spatrick
653e5dd7070Spatrick // C++ [basic.link]p3:
654e5dd7070Spatrick // A name having namespace scope (3.3.6) has internal linkage if it
655e5dd7070Spatrick // is the name of
656e5dd7070Spatrick
657e5dd7070Spatrick if (getStorageClass(D->getCanonicalDecl()) == SC_Static) {
658e5dd7070Spatrick // - a variable, variable template, function, or function template
659e5dd7070Spatrick // that is explicitly declared static; or
660e5dd7070Spatrick // (This bullet corresponds to C99 6.2.2p3.)
661e5dd7070Spatrick return getInternalLinkageFor(D);
662e5dd7070Spatrick }
663e5dd7070Spatrick
664e5dd7070Spatrick if (const auto *Var = dyn_cast<VarDecl>(D)) {
665e5dd7070Spatrick // - a non-template variable of non-volatile const-qualified type, unless
666e5dd7070Spatrick // - it is explicitly declared extern, or
667e5dd7070Spatrick // - it is inline or exported, or
668e5dd7070Spatrick // - it was previously declared and the prior declaration did not have
669e5dd7070Spatrick // internal linkage
670e5dd7070Spatrick // (There is no equivalent in C99.)
671e5dd7070Spatrick if (Context.getLangOpts().CPlusPlus &&
672e5dd7070Spatrick Var->getType().isConstQualified() &&
673e5dd7070Spatrick !Var->getType().isVolatileQualified() &&
674e5dd7070Spatrick !Var->isInline() &&
675e5dd7070Spatrick !isExportedFromModuleInterfaceUnit(Var) &&
676e5dd7070Spatrick !isa<VarTemplateSpecializationDecl>(Var) &&
677e5dd7070Spatrick !Var->getDescribedVarTemplate()) {
678e5dd7070Spatrick const VarDecl *PrevVar = Var->getPreviousDecl();
679e5dd7070Spatrick if (PrevVar)
680e5dd7070Spatrick return getLVForDecl(PrevVar, computation);
681e5dd7070Spatrick
682e5dd7070Spatrick if (Var->getStorageClass() != SC_Extern &&
683e5dd7070Spatrick Var->getStorageClass() != SC_PrivateExtern &&
684e5dd7070Spatrick !isSingleLineLanguageLinkage(*Var))
685e5dd7070Spatrick return getInternalLinkageFor(Var);
686e5dd7070Spatrick }
687e5dd7070Spatrick
688e5dd7070Spatrick for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar;
689e5dd7070Spatrick PrevVar = PrevVar->getPreviousDecl()) {
690e5dd7070Spatrick if (PrevVar->getStorageClass() == SC_PrivateExtern &&
691e5dd7070Spatrick Var->getStorageClass() == SC_None)
692e5dd7070Spatrick return getDeclLinkageAndVisibility(PrevVar);
693e5dd7070Spatrick // Explicitly declared static.
694e5dd7070Spatrick if (PrevVar->getStorageClass() == SC_Static)
695e5dd7070Spatrick return getInternalLinkageFor(Var);
696e5dd7070Spatrick }
697e5dd7070Spatrick } else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) {
698e5dd7070Spatrick // - a data member of an anonymous union.
699e5dd7070Spatrick const VarDecl *VD = IFD->getVarDecl();
700e5dd7070Spatrick assert(VD && "Expected a VarDecl in this IndirectFieldDecl!");
701e5dd7070Spatrick return getLVForNamespaceScopeDecl(VD, computation, IgnoreVarTypeLinkage);
702e5dd7070Spatrick }
703e5dd7070Spatrick assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!");
704e5dd7070Spatrick
705e5dd7070Spatrick // FIXME: This gives internal linkage to names that should have no linkage
706e5dd7070Spatrick // (those not covered by [basic.link]p6).
707e5dd7070Spatrick if (D->isInAnonymousNamespace()) {
708e5dd7070Spatrick const auto *Var = dyn_cast<VarDecl>(D);
709e5dd7070Spatrick const auto *Func = dyn_cast<FunctionDecl>(D);
710e5dd7070Spatrick // FIXME: The check for extern "C" here is not justified by the standard
711e5dd7070Spatrick // wording, but we retain it from the pre-DR1113 model to avoid breaking
712e5dd7070Spatrick // code.
713e5dd7070Spatrick //
714e5dd7070Spatrick // C++11 [basic.link]p4:
715e5dd7070Spatrick // An unnamed namespace or a namespace declared directly or indirectly
716e5dd7070Spatrick // within an unnamed namespace has internal linkage.
717e5dd7070Spatrick if ((!Var || !isFirstInExternCContext(Var)) &&
718e5dd7070Spatrick (!Func || !isFirstInExternCContext(Func)))
719e5dd7070Spatrick return getInternalLinkageFor(D);
720e5dd7070Spatrick }
721e5dd7070Spatrick
722e5dd7070Spatrick // Set up the defaults.
723e5dd7070Spatrick
724e5dd7070Spatrick // C99 6.2.2p5:
725e5dd7070Spatrick // If the declaration of an identifier for an object has file
726e5dd7070Spatrick // scope and no storage-class specifier, its linkage is
727e5dd7070Spatrick // external.
728e5dd7070Spatrick LinkageInfo LV = getExternalLinkageFor(D);
729e5dd7070Spatrick
730e5dd7070Spatrick if (!hasExplicitVisibilityAlready(computation)) {
731*12c85518Srobert if (std::optional<Visibility> Vis = getExplicitVisibility(D, computation)) {
732e5dd7070Spatrick LV.mergeVisibility(*Vis, true);
733e5dd7070Spatrick } else {
734e5dd7070Spatrick // If we're declared in a namespace with a visibility attribute,
735e5dd7070Spatrick // use that namespace's visibility, and it still counts as explicit.
736e5dd7070Spatrick for (const DeclContext *DC = D->getDeclContext();
737e5dd7070Spatrick !isa<TranslationUnitDecl>(DC);
738e5dd7070Spatrick DC = DC->getParent()) {
739e5dd7070Spatrick const auto *ND = dyn_cast<NamespaceDecl>(DC);
740e5dd7070Spatrick if (!ND) continue;
741*12c85518Srobert if (std::optional<Visibility> Vis =
742*12c85518Srobert getExplicitVisibility(ND, computation)) {
743e5dd7070Spatrick LV.mergeVisibility(*Vis, true);
744e5dd7070Spatrick break;
745e5dd7070Spatrick }
746e5dd7070Spatrick }
747e5dd7070Spatrick }
748e5dd7070Spatrick
749e5dd7070Spatrick // Add in global settings if the above didn't give us direct visibility.
750e5dd7070Spatrick if (!LV.isVisibilityExplicit()) {
751e5dd7070Spatrick // Use global type/value visibility as appropriate.
752e5dd7070Spatrick Visibility globalVisibility =
753e5dd7070Spatrick computation.isValueVisibility()
754e5dd7070Spatrick ? Context.getLangOpts().getValueVisibilityMode()
755e5dd7070Spatrick : Context.getLangOpts().getTypeVisibilityMode();
756e5dd7070Spatrick LV.mergeVisibility(globalVisibility, /*explicit*/ false);
757e5dd7070Spatrick
758e5dd7070Spatrick // If we're paying attention to global visibility, apply
759e5dd7070Spatrick // -finline-visibility-hidden if this is an inline method.
760e5dd7070Spatrick if (useInlineVisibilityHidden(D))
761e5dd7070Spatrick LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false);
762e5dd7070Spatrick }
763e5dd7070Spatrick }
764e5dd7070Spatrick
765e5dd7070Spatrick // C++ [basic.link]p4:
766e5dd7070Spatrick
767e5dd7070Spatrick // A name having namespace scope that has not been given internal linkage
768e5dd7070Spatrick // above and that is the name of
769e5dd7070Spatrick // [...bullets...]
770e5dd7070Spatrick // has its linkage determined as follows:
771e5dd7070Spatrick // - if the enclosing namespace has internal linkage, the name has
772e5dd7070Spatrick // internal linkage; [handled above]
773e5dd7070Spatrick // - otherwise, if the declaration of the name is attached to a named
774e5dd7070Spatrick // module and is not exported, the name has module linkage;
775e5dd7070Spatrick // - otherwise, the name has external linkage.
776e5dd7070Spatrick // LV is currently set up to handle the last two bullets.
777e5dd7070Spatrick //
778e5dd7070Spatrick // The bullets are:
779e5dd7070Spatrick
780e5dd7070Spatrick // - a variable; or
781e5dd7070Spatrick if (const auto *Var = dyn_cast<VarDecl>(D)) {
782e5dd7070Spatrick // GCC applies the following optimization to variables and static
783e5dd7070Spatrick // data members, but not to functions:
784e5dd7070Spatrick //
785e5dd7070Spatrick // Modify the variable's LV by the LV of its type unless this is
786e5dd7070Spatrick // C or extern "C". This follows from [basic.link]p9:
787e5dd7070Spatrick // A type without linkage shall not be used as the type of a
788e5dd7070Spatrick // variable or function with external linkage unless
789e5dd7070Spatrick // - the entity has C language linkage, or
790e5dd7070Spatrick // - the entity is declared within an unnamed namespace, or
791e5dd7070Spatrick // - the entity is not used or is defined in the same
792e5dd7070Spatrick // translation unit.
793e5dd7070Spatrick // and [basic.link]p10:
794e5dd7070Spatrick // ...the types specified by all declarations referring to a
795e5dd7070Spatrick // given variable or function shall be identical...
796e5dd7070Spatrick // C does not have an equivalent rule.
797e5dd7070Spatrick //
798e5dd7070Spatrick // Ignore this if we've got an explicit attribute; the user
799e5dd7070Spatrick // probably knows what they're doing.
800e5dd7070Spatrick //
801e5dd7070Spatrick // Note that we don't want to make the variable non-external
802e5dd7070Spatrick // because of this, but unique-external linkage suits us.
803*12c85518Srobert
804e5dd7070Spatrick if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var) &&
805e5dd7070Spatrick !IgnoreVarTypeLinkage) {
806e5dd7070Spatrick LinkageInfo TypeLV = getLVForType(*Var->getType(), computation);
807e5dd7070Spatrick if (!isExternallyVisible(TypeLV.getLinkage()))
808e5dd7070Spatrick return LinkageInfo::uniqueExternal();
809e5dd7070Spatrick if (!LV.isVisibilityExplicit())
810e5dd7070Spatrick LV.mergeVisibility(TypeLV);
811e5dd7070Spatrick }
812e5dd7070Spatrick
813e5dd7070Spatrick if (Var->getStorageClass() == SC_PrivateExtern)
814e5dd7070Spatrick LV.mergeVisibility(HiddenVisibility, true);
815e5dd7070Spatrick
816e5dd7070Spatrick // Note that Sema::MergeVarDecl already takes care of implementing
817e5dd7070Spatrick // C99 6.2.2p4 and propagating the visibility attribute, so we don't have
818e5dd7070Spatrick // to do it here.
819e5dd7070Spatrick
820e5dd7070Spatrick // As per function and class template specializations (below),
821e5dd7070Spatrick // consider LV for the template and template arguments. We're at file
822e5dd7070Spatrick // scope, so we do not need to worry about nested specializations.
823e5dd7070Spatrick if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(Var)) {
824e5dd7070Spatrick mergeTemplateLV(LV, spec, computation);
825e5dd7070Spatrick }
826e5dd7070Spatrick
827e5dd7070Spatrick // - a function; or
828e5dd7070Spatrick } else if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
829e5dd7070Spatrick // In theory, we can modify the function's LV by the LV of its
830e5dd7070Spatrick // type unless it has C linkage (see comment above about variables
831e5dd7070Spatrick // for justification). In practice, GCC doesn't do this, so it's
832e5dd7070Spatrick // just too painful to make work.
833e5dd7070Spatrick
834e5dd7070Spatrick if (Function->getStorageClass() == SC_PrivateExtern)
835e5dd7070Spatrick LV.mergeVisibility(HiddenVisibility, true);
836e5dd7070Spatrick
837*12c85518Srobert // OpenMP target declare device functions are not callable from the host so
838*12c85518Srobert // they should not be exported from the device image. This applies to all
839*12c85518Srobert // functions as the host-callable kernel functions are emitted at codegen.
840*12c85518Srobert if (Context.getLangOpts().OpenMP && Context.getLangOpts().OpenMPIsDevice &&
841*12c85518Srobert ((Context.getTargetInfo().getTriple().isAMDGPU() ||
842*12c85518Srobert Context.getTargetInfo().getTriple().isNVPTX()) ||
843*12c85518Srobert OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Function)))
844*12c85518Srobert LV.mergeVisibility(HiddenVisibility, /*newExplicit=*/false);
845*12c85518Srobert
846e5dd7070Spatrick // Note that Sema::MergeCompatibleFunctionDecls already takes care of
847e5dd7070Spatrick // merging storage classes and visibility attributes, so we don't have to
848e5dd7070Spatrick // look at previous decls in here.
849e5dd7070Spatrick
850e5dd7070Spatrick // In C++, then if the type of the function uses a type with
851e5dd7070Spatrick // unique-external linkage, it's not legally usable from outside
852e5dd7070Spatrick // this translation unit. However, we should use the C linkage
853e5dd7070Spatrick // rules instead for extern "C" declarations.
854e5dd7070Spatrick if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Function)) {
855e5dd7070Spatrick // Only look at the type-as-written. Otherwise, deducing the return type
856e5dd7070Spatrick // of a function could change its linkage.
857e5dd7070Spatrick QualType TypeAsWritten = Function->getType();
858e5dd7070Spatrick if (TypeSourceInfo *TSI = Function->getTypeSourceInfo())
859e5dd7070Spatrick TypeAsWritten = TSI->getType();
860e5dd7070Spatrick if (!isExternallyVisible(TypeAsWritten->getLinkage()))
861e5dd7070Spatrick return LinkageInfo::uniqueExternal();
862e5dd7070Spatrick }
863e5dd7070Spatrick
864e5dd7070Spatrick // Consider LV from the template and the template arguments.
865e5dd7070Spatrick // We're at file scope, so we do not need to worry about nested
866e5dd7070Spatrick // specializations.
867e5dd7070Spatrick if (FunctionTemplateSpecializationInfo *specInfo
868e5dd7070Spatrick = Function->getTemplateSpecializationInfo()) {
869e5dd7070Spatrick mergeTemplateLV(LV, Function, specInfo, computation);
870e5dd7070Spatrick }
871e5dd7070Spatrick
872e5dd7070Spatrick // - a named class (Clause 9), or an unnamed class defined in a
873e5dd7070Spatrick // typedef declaration in which the class has the typedef name
874e5dd7070Spatrick // for linkage purposes (7.1.3); or
875e5dd7070Spatrick // - a named enumeration (7.2), or an unnamed enumeration
876e5dd7070Spatrick // defined in a typedef declaration in which the enumeration
877e5dd7070Spatrick // has the typedef name for linkage purposes (7.1.3); or
878e5dd7070Spatrick } else if (const auto *Tag = dyn_cast<TagDecl>(D)) {
879e5dd7070Spatrick // Unnamed tags have no linkage.
880e5dd7070Spatrick if (!Tag->hasNameForLinkage())
881e5dd7070Spatrick return LinkageInfo::none();
882e5dd7070Spatrick
883e5dd7070Spatrick // If this is a class template specialization, consider the
884e5dd7070Spatrick // linkage of the template and template arguments. We're at file
885e5dd7070Spatrick // scope, so we do not need to worry about nested specializations.
886e5dd7070Spatrick if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
887e5dd7070Spatrick mergeTemplateLV(LV, spec, computation);
888e5dd7070Spatrick }
889e5dd7070Spatrick
890e5dd7070Spatrick // FIXME: This is not part of the C++ standard any more.
891e5dd7070Spatrick // - an enumerator belonging to an enumeration with external linkage; or
892e5dd7070Spatrick } else if (isa<EnumConstantDecl>(D)) {
893e5dd7070Spatrick LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()),
894e5dd7070Spatrick computation);
895e5dd7070Spatrick if (!isExternalFormalLinkage(EnumLV.getLinkage()))
896e5dd7070Spatrick return LinkageInfo::none();
897e5dd7070Spatrick LV.merge(EnumLV);
898e5dd7070Spatrick
899e5dd7070Spatrick // - a template
900e5dd7070Spatrick } else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
901e5dd7070Spatrick bool considerVisibility = !hasExplicitVisibilityAlready(computation);
902e5dd7070Spatrick LinkageInfo tempLV =
903e5dd7070Spatrick getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
904e5dd7070Spatrick LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
905e5dd7070Spatrick
906e5dd7070Spatrick // An unnamed namespace or a namespace declared directly or indirectly
907e5dd7070Spatrick // within an unnamed namespace has internal linkage. All other namespaces
908e5dd7070Spatrick // have external linkage.
909e5dd7070Spatrick //
910e5dd7070Spatrick // We handled names in anonymous namespaces above.
911e5dd7070Spatrick } else if (isa<NamespaceDecl>(D)) {
912e5dd7070Spatrick return LV;
913e5dd7070Spatrick
914e5dd7070Spatrick // By extension, we assign external linkage to Objective-C
915e5dd7070Spatrick // interfaces.
916e5dd7070Spatrick } else if (isa<ObjCInterfaceDecl>(D)) {
917e5dd7070Spatrick // fallout
918e5dd7070Spatrick
919e5dd7070Spatrick } else if (auto *TD = dyn_cast<TypedefNameDecl>(D)) {
920e5dd7070Spatrick // A typedef declaration has linkage if it gives a type a name for
921e5dd7070Spatrick // linkage purposes.
922e5dd7070Spatrick if (!TD->getAnonDeclWithTypedefName(/*AnyRedecl*/true))
923e5dd7070Spatrick return LinkageInfo::none();
924e5dd7070Spatrick
925ec727ea7Spatrick } else if (isa<MSGuidDecl>(D)) {
926ec727ea7Spatrick // A GUID behaves like an inline variable with external linkage. Fall
927ec727ea7Spatrick // through.
928ec727ea7Spatrick
929e5dd7070Spatrick // Everything not covered here has no linkage.
930e5dd7070Spatrick } else {
931e5dd7070Spatrick return LinkageInfo::none();
932e5dd7070Spatrick }
933e5dd7070Spatrick
934e5dd7070Spatrick // If we ended up with non-externally-visible linkage, visibility should
935e5dd7070Spatrick // always be default.
936e5dd7070Spatrick if (!isExternallyVisible(LV.getLinkage()))
937e5dd7070Spatrick return LinkageInfo(LV.getLinkage(), DefaultVisibility, false);
938e5dd7070Spatrick
939e5dd7070Spatrick return LV;
940e5dd7070Spatrick }
941e5dd7070Spatrick
942e5dd7070Spatrick LinkageInfo
getLVForClassMember(const NamedDecl * D,LVComputationKind computation,bool IgnoreVarTypeLinkage)943e5dd7070Spatrick LinkageComputer::getLVForClassMember(const NamedDecl *D,
944e5dd7070Spatrick LVComputationKind computation,
945e5dd7070Spatrick bool IgnoreVarTypeLinkage) {
946e5dd7070Spatrick // Only certain class members have linkage. Note that fields don't
947e5dd7070Spatrick // really have linkage, but it's convenient to say they do for the
948e5dd7070Spatrick // purposes of calculating linkage of pointer-to-data-member
949e5dd7070Spatrick // template arguments.
950e5dd7070Spatrick //
951e5dd7070Spatrick // Templates also don't officially have linkage, but since we ignore
952e5dd7070Spatrick // the C++ standard and look at template arguments when determining
953e5dd7070Spatrick // linkage and visibility of a template specialization, we might hit
954e5dd7070Spatrick // a template template argument that way. If we do, we need to
955e5dd7070Spatrick // consider its linkage.
956e5dd7070Spatrick if (!(isa<CXXMethodDecl>(D) ||
957e5dd7070Spatrick isa<VarDecl>(D) ||
958e5dd7070Spatrick isa<FieldDecl>(D) ||
959e5dd7070Spatrick isa<IndirectFieldDecl>(D) ||
960e5dd7070Spatrick isa<TagDecl>(D) ||
961e5dd7070Spatrick isa<TemplateDecl>(D)))
962e5dd7070Spatrick return LinkageInfo::none();
963e5dd7070Spatrick
964e5dd7070Spatrick LinkageInfo LV;
965e5dd7070Spatrick
966e5dd7070Spatrick // If we have an explicit visibility attribute, merge that in.
967e5dd7070Spatrick if (!hasExplicitVisibilityAlready(computation)) {
968*12c85518Srobert if (std::optional<Visibility> Vis = getExplicitVisibility(D, computation))
969e5dd7070Spatrick LV.mergeVisibility(*Vis, true);
970e5dd7070Spatrick // If we're paying attention to global visibility, apply
971e5dd7070Spatrick // -finline-visibility-hidden if this is an inline method.
972e5dd7070Spatrick //
973e5dd7070Spatrick // Note that we do this before merging information about
974e5dd7070Spatrick // the class visibility.
975e5dd7070Spatrick if (!LV.isVisibilityExplicit() && useInlineVisibilityHidden(D))
976e5dd7070Spatrick LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false);
977e5dd7070Spatrick }
978e5dd7070Spatrick
979e5dd7070Spatrick // If this class member has an explicit visibility attribute, the only
980e5dd7070Spatrick // thing that can change its visibility is the template arguments, so
981e5dd7070Spatrick // only look for them when processing the class.
982e5dd7070Spatrick LVComputationKind classComputation = computation;
983e5dd7070Spatrick if (LV.isVisibilityExplicit())
984e5dd7070Spatrick classComputation = withExplicitVisibilityAlready(computation);
985e5dd7070Spatrick
986e5dd7070Spatrick LinkageInfo classLV =
987e5dd7070Spatrick getLVForDecl(cast<RecordDecl>(D->getDeclContext()), classComputation);
988e5dd7070Spatrick // The member has the same linkage as the class. If that's not externally
989e5dd7070Spatrick // visible, we don't need to compute anything about the linkage.
990e5dd7070Spatrick // FIXME: If we're only computing linkage, can we bail out here?
991e5dd7070Spatrick if (!isExternallyVisible(classLV.getLinkage()))
992e5dd7070Spatrick return classLV;
993e5dd7070Spatrick
994e5dd7070Spatrick
995e5dd7070Spatrick // Otherwise, don't merge in classLV yet, because in certain cases
996e5dd7070Spatrick // we need to completely ignore the visibility from it.
997e5dd7070Spatrick
998e5dd7070Spatrick // Specifically, if this decl exists and has an explicit attribute.
999e5dd7070Spatrick const NamedDecl *explicitSpecSuppressor = nullptr;
1000e5dd7070Spatrick
1001e5dd7070Spatrick if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
1002e5dd7070Spatrick // Only look at the type-as-written. Otherwise, deducing the return type
1003e5dd7070Spatrick // of a function could change its linkage.
1004e5dd7070Spatrick QualType TypeAsWritten = MD->getType();
1005e5dd7070Spatrick if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
1006e5dd7070Spatrick TypeAsWritten = TSI->getType();
1007e5dd7070Spatrick if (!isExternallyVisible(TypeAsWritten->getLinkage()))
1008e5dd7070Spatrick return LinkageInfo::uniqueExternal();
1009e5dd7070Spatrick
1010e5dd7070Spatrick // If this is a method template specialization, use the linkage for
1011e5dd7070Spatrick // the template parameters and arguments.
1012e5dd7070Spatrick if (FunctionTemplateSpecializationInfo *spec
1013e5dd7070Spatrick = MD->getTemplateSpecializationInfo()) {
1014e5dd7070Spatrick mergeTemplateLV(LV, MD, spec, computation);
1015e5dd7070Spatrick if (spec->isExplicitSpecialization()) {
1016e5dd7070Spatrick explicitSpecSuppressor = MD;
1017e5dd7070Spatrick } else if (isExplicitMemberSpecialization(spec->getTemplate())) {
1018e5dd7070Spatrick explicitSpecSuppressor = spec->getTemplate()->getTemplatedDecl();
1019e5dd7070Spatrick }
1020e5dd7070Spatrick } else if (isExplicitMemberSpecialization(MD)) {
1021e5dd7070Spatrick explicitSpecSuppressor = MD;
1022e5dd7070Spatrick }
1023e5dd7070Spatrick
1024*12c85518Srobert // OpenMP target declare device functions are not callable from the host so
1025*12c85518Srobert // they should not be exported from the device image. This applies to all
1026*12c85518Srobert // functions as the host-callable kernel functions are emitted at codegen.
1027*12c85518Srobert ASTContext &Context = D->getASTContext();
1028*12c85518Srobert if (Context.getLangOpts().OpenMP && Context.getLangOpts().OpenMPIsDevice &&
1029*12c85518Srobert ((Context.getTargetInfo().getTriple().isAMDGPU() ||
1030*12c85518Srobert Context.getTargetInfo().getTriple().isNVPTX()) ||
1031*12c85518Srobert OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(MD)))
1032*12c85518Srobert LV.mergeVisibility(HiddenVisibility, /*newExplicit=*/false);
1033*12c85518Srobert
1034e5dd7070Spatrick } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
1035e5dd7070Spatrick if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
1036e5dd7070Spatrick mergeTemplateLV(LV, spec, computation);
1037e5dd7070Spatrick if (spec->isExplicitSpecialization()) {
1038e5dd7070Spatrick explicitSpecSuppressor = spec;
1039e5dd7070Spatrick } else {
1040e5dd7070Spatrick const ClassTemplateDecl *temp = spec->getSpecializedTemplate();
1041e5dd7070Spatrick if (isExplicitMemberSpecialization(temp)) {
1042e5dd7070Spatrick explicitSpecSuppressor = temp->getTemplatedDecl();
1043e5dd7070Spatrick }
1044e5dd7070Spatrick }
1045e5dd7070Spatrick } else if (isExplicitMemberSpecialization(RD)) {
1046e5dd7070Spatrick explicitSpecSuppressor = RD;
1047e5dd7070Spatrick }
1048e5dd7070Spatrick
1049e5dd7070Spatrick // Static data members.
1050e5dd7070Spatrick } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
1051e5dd7070Spatrick if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(VD))
1052e5dd7070Spatrick mergeTemplateLV(LV, spec, computation);
1053e5dd7070Spatrick
1054e5dd7070Spatrick // Modify the variable's linkage by its type, but ignore the
1055e5dd7070Spatrick // type's visibility unless it's a definition.
1056e5dd7070Spatrick if (!IgnoreVarTypeLinkage) {
1057e5dd7070Spatrick LinkageInfo typeLV = getLVForType(*VD->getType(), computation);
1058e5dd7070Spatrick // FIXME: If the type's linkage is not externally visible, we can
1059e5dd7070Spatrick // give this static data member UniqueExternalLinkage.
1060e5dd7070Spatrick if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit())
1061e5dd7070Spatrick LV.mergeVisibility(typeLV);
1062e5dd7070Spatrick LV.mergeExternalVisibility(typeLV);
1063e5dd7070Spatrick }
1064e5dd7070Spatrick
1065e5dd7070Spatrick if (isExplicitMemberSpecialization(VD)) {
1066e5dd7070Spatrick explicitSpecSuppressor = VD;
1067e5dd7070Spatrick }
1068e5dd7070Spatrick
1069e5dd7070Spatrick // Template members.
1070e5dd7070Spatrick } else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
1071e5dd7070Spatrick bool considerVisibility =
1072e5dd7070Spatrick (!LV.isVisibilityExplicit() &&
1073e5dd7070Spatrick !classLV.isVisibilityExplicit() &&
1074e5dd7070Spatrick !hasExplicitVisibilityAlready(computation));
1075e5dd7070Spatrick LinkageInfo tempLV =
1076e5dd7070Spatrick getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
1077e5dd7070Spatrick LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
1078e5dd7070Spatrick
1079e5dd7070Spatrick if (const auto *redeclTemp = dyn_cast<RedeclarableTemplateDecl>(temp)) {
1080e5dd7070Spatrick if (isExplicitMemberSpecialization(redeclTemp)) {
1081e5dd7070Spatrick explicitSpecSuppressor = temp->getTemplatedDecl();
1082e5dd7070Spatrick }
1083e5dd7070Spatrick }
1084e5dd7070Spatrick }
1085e5dd7070Spatrick
1086e5dd7070Spatrick // We should never be looking for an attribute directly on a template.
1087e5dd7070Spatrick assert(!explicitSpecSuppressor || !isa<TemplateDecl>(explicitSpecSuppressor));
1088e5dd7070Spatrick
1089e5dd7070Spatrick // If this member is an explicit member specialization, and it has
1090e5dd7070Spatrick // an explicit attribute, ignore visibility from the parent.
1091e5dd7070Spatrick bool considerClassVisibility = true;
1092e5dd7070Spatrick if (explicitSpecSuppressor &&
1093e5dd7070Spatrick // optimization: hasDVA() is true only with explicit visibility.
1094e5dd7070Spatrick LV.isVisibilityExplicit() &&
1095e5dd7070Spatrick classLV.getVisibility() != DefaultVisibility &&
1096e5dd7070Spatrick hasDirectVisibilityAttribute(explicitSpecSuppressor, computation)) {
1097e5dd7070Spatrick considerClassVisibility = false;
1098e5dd7070Spatrick }
1099e5dd7070Spatrick
1100e5dd7070Spatrick // Finally, merge in information from the class.
1101e5dd7070Spatrick LV.mergeMaybeWithVisibility(classLV, considerClassVisibility);
1102e5dd7070Spatrick return LV;
1103e5dd7070Spatrick }
1104e5dd7070Spatrick
anchor()1105e5dd7070Spatrick void NamedDecl::anchor() {}
1106e5dd7070Spatrick
isLinkageValid() const1107e5dd7070Spatrick bool NamedDecl::isLinkageValid() const {
1108e5dd7070Spatrick if (!hasCachedLinkage())
1109e5dd7070Spatrick return true;
1110e5dd7070Spatrick
1111e5dd7070Spatrick Linkage L = LinkageComputer{}
1112e5dd7070Spatrick .computeLVForDecl(this, LVComputationKind::forLinkageOnly())
1113e5dd7070Spatrick .getLinkage();
1114e5dd7070Spatrick return L == getCachedLinkage();
1115e5dd7070Spatrick }
1116e5dd7070Spatrick
1117a9ac8606Spatrick ReservedIdentifierStatus
isReserved(const LangOptions & LangOpts) const1118a9ac8606Spatrick NamedDecl::isReserved(const LangOptions &LangOpts) const {
1119a9ac8606Spatrick const IdentifierInfo *II = getIdentifier();
1120a9ac8606Spatrick
1121a9ac8606Spatrick // This triggers at least for CXXLiteralIdentifiers, which we already checked
1122a9ac8606Spatrick // at lexing time.
1123a9ac8606Spatrick if (!II)
1124a9ac8606Spatrick return ReservedIdentifierStatus::NotReserved;
1125a9ac8606Spatrick
1126a9ac8606Spatrick ReservedIdentifierStatus Status = II->isReserved(LangOpts);
1127*12c85518Srobert if (isReservedAtGlobalScope(Status) && !isReservedInAllContexts(Status)) {
1128*12c85518Srobert // This name is only reserved at global scope. Check if this declaration
1129*12c85518Srobert // conflicts with a global scope declaration.
1130a9ac8606Spatrick if (isa<ParmVarDecl>(this) || isTemplateParameter())
1131a9ac8606Spatrick return ReservedIdentifierStatus::NotReserved;
1132*12c85518Srobert
1133*12c85518Srobert // C++ [dcl.link]/7:
1134*12c85518Srobert // Two declarations [conflict] if [...] one declares a function or
1135*12c85518Srobert // variable with C language linkage, and the other declares [...] a
1136*12c85518Srobert // variable that belongs to the global scope.
1137*12c85518Srobert //
1138*12c85518Srobert // Therefore names that are reserved at global scope are also reserved as
1139*12c85518Srobert // names of variables and functions with C language linkage.
1140a9ac8606Spatrick const DeclContext *DC = getDeclContext()->getRedeclContext();
1141*12c85518Srobert if (DC->isTranslationUnit())
1142*12c85518Srobert return Status;
1143*12c85518Srobert if (auto *VD = dyn_cast<VarDecl>(this))
1144*12c85518Srobert if (VD->isExternC())
1145*12c85518Srobert return ReservedIdentifierStatus::StartsWithUnderscoreAndIsExternC;
1146*12c85518Srobert if (auto *FD = dyn_cast<FunctionDecl>(this))
1147*12c85518Srobert if (FD->isExternC())
1148*12c85518Srobert return ReservedIdentifierStatus::StartsWithUnderscoreAndIsExternC;
1149a9ac8606Spatrick return ReservedIdentifierStatus::NotReserved;
1150a9ac8606Spatrick }
1151a9ac8606Spatrick
1152a9ac8606Spatrick return Status;
1153a9ac8606Spatrick }
1154a9ac8606Spatrick
getObjCFStringFormattingFamily() const1155e5dd7070Spatrick ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const {
1156e5dd7070Spatrick StringRef name = getName();
1157e5dd7070Spatrick if (name.empty()) return SFF_None;
1158e5dd7070Spatrick
1159e5dd7070Spatrick if (name.front() == 'C')
1160e5dd7070Spatrick if (name == "CFStringCreateWithFormat" ||
1161e5dd7070Spatrick name == "CFStringCreateWithFormatAndArguments" ||
1162e5dd7070Spatrick name == "CFStringAppendFormat" ||
1163e5dd7070Spatrick name == "CFStringAppendFormatAndArguments")
1164e5dd7070Spatrick return SFF_CFString;
1165e5dd7070Spatrick return SFF_None;
1166e5dd7070Spatrick }
1167e5dd7070Spatrick
getLinkageInternal() const1168e5dd7070Spatrick Linkage NamedDecl::getLinkageInternal() const {
1169e5dd7070Spatrick // We don't care about visibility here, so ask for the cheapest
1170e5dd7070Spatrick // possible visibility analysis.
1171e5dd7070Spatrick return LinkageComputer{}
1172e5dd7070Spatrick .getLVForDecl(this, LVComputationKind::forLinkageOnly())
1173e5dd7070Spatrick .getLinkage();
1174e5dd7070Spatrick }
1175e5dd7070Spatrick
getLinkageAndVisibility() const1176e5dd7070Spatrick LinkageInfo NamedDecl::getLinkageAndVisibility() const {
1177e5dd7070Spatrick return LinkageComputer{}.getDeclLinkageAndVisibility(this);
1178e5dd7070Spatrick }
1179e5dd7070Spatrick
1180*12c85518Srobert static std::optional<Visibility>
getExplicitVisibilityAux(const NamedDecl * ND,NamedDecl::ExplicitVisibilityKind kind,bool IsMostRecent)1181e5dd7070Spatrick getExplicitVisibilityAux(const NamedDecl *ND,
1182e5dd7070Spatrick NamedDecl::ExplicitVisibilityKind kind,
1183e5dd7070Spatrick bool IsMostRecent) {
1184e5dd7070Spatrick assert(!IsMostRecent || ND == ND->getMostRecentDecl());
1185e5dd7070Spatrick
1186e5dd7070Spatrick // Check the declaration itself first.
1187*12c85518Srobert if (std::optional<Visibility> V = getVisibilityOf(ND, kind))
1188e5dd7070Spatrick return V;
1189e5dd7070Spatrick
1190e5dd7070Spatrick // If this is a member class of a specialization of a class template
1191e5dd7070Spatrick // and the corresponding decl has explicit visibility, use that.
1192e5dd7070Spatrick if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
1193e5dd7070Spatrick CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
1194e5dd7070Spatrick if (InstantiatedFrom)
1195e5dd7070Spatrick return getVisibilityOf(InstantiatedFrom, kind);
1196e5dd7070Spatrick }
1197e5dd7070Spatrick
1198e5dd7070Spatrick // If there wasn't explicit visibility there, and this is a
1199e5dd7070Spatrick // specialization of a class template, check for visibility
1200e5dd7070Spatrick // on the pattern.
1201e5dd7070Spatrick if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
1202e5dd7070Spatrick // Walk all the template decl till this point to see if there are
1203e5dd7070Spatrick // explicit visibility attributes.
1204e5dd7070Spatrick const auto *TD = spec->getSpecializedTemplate()->getTemplatedDecl();
1205e5dd7070Spatrick while (TD != nullptr) {
1206e5dd7070Spatrick auto Vis = getVisibilityOf(TD, kind);
1207*12c85518Srobert if (Vis != std::nullopt)
1208e5dd7070Spatrick return Vis;
1209e5dd7070Spatrick TD = TD->getPreviousDecl();
1210e5dd7070Spatrick }
1211*12c85518Srobert return std::nullopt;
1212e5dd7070Spatrick }
1213e5dd7070Spatrick
1214e5dd7070Spatrick // Use the most recent declaration.
1215e5dd7070Spatrick if (!IsMostRecent && !isa<NamespaceDecl>(ND)) {
1216e5dd7070Spatrick const NamedDecl *MostRecent = ND->getMostRecentDecl();
1217e5dd7070Spatrick if (MostRecent != ND)
1218e5dd7070Spatrick return getExplicitVisibilityAux(MostRecent, kind, true);
1219e5dd7070Spatrick }
1220e5dd7070Spatrick
1221e5dd7070Spatrick if (const auto *Var = dyn_cast<VarDecl>(ND)) {
1222e5dd7070Spatrick if (Var->isStaticDataMember()) {
1223e5dd7070Spatrick VarDecl *InstantiatedFrom = Var->getInstantiatedFromStaticDataMember();
1224e5dd7070Spatrick if (InstantiatedFrom)
1225e5dd7070Spatrick return getVisibilityOf(InstantiatedFrom, kind);
1226e5dd7070Spatrick }
1227e5dd7070Spatrick
1228e5dd7070Spatrick if (const auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Var))
1229e5dd7070Spatrick return getVisibilityOf(VTSD->getSpecializedTemplate()->getTemplatedDecl(),
1230e5dd7070Spatrick kind);
1231e5dd7070Spatrick
1232*12c85518Srobert return std::nullopt;
1233e5dd7070Spatrick }
1234e5dd7070Spatrick // Also handle function template specializations.
1235e5dd7070Spatrick if (const auto *fn = dyn_cast<FunctionDecl>(ND)) {
1236e5dd7070Spatrick // If the function is a specialization of a template with an
1237e5dd7070Spatrick // explicit visibility attribute, use that.
1238e5dd7070Spatrick if (FunctionTemplateSpecializationInfo *templateInfo
1239e5dd7070Spatrick = fn->getTemplateSpecializationInfo())
1240e5dd7070Spatrick return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl(),
1241e5dd7070Spatrick kind);
1242e5dd7070Spatrick
1243e5dd7070Spatrick // If the function is a member of a specialization of a class template
1244e5dd7070Spatrick // and the corresponding decl has explicit visibility, use that.
1245e5dd7070Spatrick FunctionDecl *InstantiatedFrom = fn->getInstantiatedFromMemberFunction();
1246e5dd7070Spatrick if (InstantiatedFrom)
1247e5dd7070Spatrick return getVisibilityOf(InstantiatedFrom, kind);
1248e5dd7070Spatrick
1249*12c85518Srobert return std::nullopt;
1250e5dd7070Spatrick }
1251e5dd7070Spatrick
1252e5dd7070Spatrick // The visibility of a template is stored in the templated decl.
1253e5dd7070Spatrick if (const auto *TD = dyn_cast<TemplateDecl>(ND))
1254e5dd7070Spatrick return getVisibilityOf(TD->getTemplatedDecl(), kind);
1255e5dd7070Spatrick
1256*12c85518Srobert return std::nullopt;
1257e5dd7070Spatrick }
1258e5dd7070Spatrick
1259*12c85518Srobert std::optional<Visibility>
getExplicitVisibility(ExplicitVisibilityKind kind) const1260e5dd7070Spatrick NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
1261e5dd7070Spatrick return getExplicitVisibilityAux(this, kind, false);
1262e5dd7070Spatrick }
1263e5dd7070Spatrick
getLVForClosure(const DeclContext * DC,Decl * ContextDecl,LVComputationKind computation)1264e5dd7070Spatrick LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC,
1265e5dd7070Spatrick Decl *ContextDecl,
1266e5dd7070Spatrick LVComputationKind computation) {
1267e5dd7070Spatrick // This lambda has its linkage/visibility determined by its owner.
1268e5dd7070Spatrick const NamedDecl *Owner;
1269e5dd7070Spatrick if (!ContextDecl)
1270e5dd7070Spatrick Owner = dyn_cast<NamedDecl>(DC);
1271e5dd7070Spatrick else if (isa<ParmVarDecl>(ContextDecl))
1272e5dd7070Spatrick Owner =
1273e5dd7070Spatrick dyn_cast<NamedDecl>(ContextDecl->getDeclContext()->getRedeclContext());
1274*12c85518Srobert else if (isa<ImplicitConceptSpecializationDecl>(ContextDecl)) {
1275*12c85518Srobert // Replace with the concept's owning decl, which is either a namespace or a
1276*12c85518Srobert // TU, so this needs a dyn_cast.
1277*12c85518Srobert Owner = dyn_cast<NamedDecl>(ContextDecl->getDeclContext());
1278*12c85518Srobert } else {
1279e5dd7070Spatrick Owner = cast<NamedDecl>(ContextDecl);
1280*12c85518Srobert }
1281e5dd7070Spatrick
1282e5dd7070Spatrick if (!Owner)
1283e5dd7070Spatrick return LinkageInfo::none();
1284e5dd7070Spatrick
1285e5dd7070Spatrick // If the owner has a deduced type, we need to skip querying the linkage and
1286e5dd7070Spatrick // visibility of that type, because it might involve this closure type. The
1287e5dd7070Spatrick // only effect of this is that we might give a lambda VisibleNoLinkage rather
1288e5dd7070Spatrick // than NoLinkage when we don't strictly need to, which is benign.
1289e5dd7070Spatrick auto *VD = dyn_cast<VarDecl>(Owner);
1290e5dd7070Spatrick LinkageInfo OwnerLV =
1291e5dd7070Spatrick VD && VD->getType()->getContainedDeducedType()
1292e5dd7070Spatrick ? computeLVForDecl(Owner, computation, /*IgnoreVarTypeLinkage*/true)
1293e5dd7070Spatrick : getLVForDecl(Owner, computation);
1294e5dd7070Spatrick
1295e5dd7070Spatrick // A lambda never formally has linkage. But if the owner is externally
1296e5dd7070Spatrick // visible, then the lambda is too. We apply the same rules to blocks.
1297e5dd7070Spatrick if (!isExternallyVisible(OwnerLV.getLinkage()))
1298e5dd7070Spatrick return LinkageInfo::none();
1299e5dd7070Spatrick return LinkageInfo(VisibleNoLinkage, OwnerLV.getVisibility(),
1300e5dd7070Spatrick OwnerLV.isVisibilityExplicit());
1301e5dd7070Spatrick }
1302e5dd7070Spatrick
getLVForLocalDecl(const NamedDecl * D,LVComputationKind computation)1303e5dd7070Spatrick LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
1304e5dd7070Spatrick LVComputationKind computation) {
1305e5dd7070Spatrick if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
1306e5dd7070Spatrick if (Function->isInAnonymousNamespace() &&
1307e5dd7070Spatrick !isFirstInExternCContext(Function))
1308e5dd7070Spatrick return getInternalLinkageFor(Function);
1309e5dd7070Spatrick
1310e5dd7070Spatrick // This is a "void f();" which got merged with a file static.
1311e5dd7070Spatrick if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
1312e5dd7070Spatrick return getInternalLinkageFor(Function);
1313e5dd7070Spatrick
1314e5dd7070Spatrick LinkageInfo LV;
1315e5dd7070Spatrick if (!hasExplicitVisibilityAlready(computation)) {
1316*12c85518Srobert if (std::optional<Visibility> Vis =
1317e5dd7070Spatrick getExplicitVisibility(Function, computation))
1318e5dd7070Spatrick LV.mergeVisibility(*Vis, true);
1319e5dd7070Spatrick }
1320e5dd7070Spatrick
1321e5dd7070Spatrick // Note that Sema::MergeCompatibleFunctionDecls already takes care of
1322e5dd7070Spatrick // merging storage classes and visibility attributes, so we don't have to
1323e5dd7070Spatrick // look at previous decls in here.
1324e5dd7070Spatrick
1325e5dd7070Spatrick return LV;
1326e5dd7070Spatrick }
1327e5dd7070Spatrick
1328e5dd7070Spatrick if (const auto *Var = dyn_cast<VarDecl>(D)) {
1329e5dd7070Spatrick if (Var->hasExternalStorage()) {
1330e5dd7070Spatrick if (Var->isInAnonymousNamespace() && !isFirstInExternCContext(Var))
1331e5dd7070Spatrick return getInternalLinkageFor(Var);
1332e5dd7070Spatrick
1333e5dd7070Spatrick LinkageInfo LV;
1334e5dd7070Spatrick if (Var->getStorageClass() == SC_PrivateExtern)
1335e5dd7070Spatrick LV.mergeVisibility(HiddenVisibility, true);
1336e5dd7070Spatrick else if (!hasExplicitVisibilityAlready(computation)) {
1337*12c85518Srobert if (std::optional<Visibility> Vis =
1338*12c85518Srobert getExplicitVisibility(Var, computation))
1339e5dd7070Spatrick LV.mergeVisibility(*Vis, true);
1340e5dd7070Spatrick }
1341e5dd7070Spatrick
1342e5dd7070Spatrick if (const VarDecl *Prev = Var->getPreviousDecl()) {
1343e5dd7070Spatrick LinkageInfo PrevLV = getLVForDecl(Prev, computation);
1344e5dd7070Spatrick if (PrevLV.getLinkage())
1345e5dd7070Spatrick LV.setLinkage(PrevLV.getLinkage());
1346e5dd7070Spatrick LV.mergeVisibility(PrevLV);
1347e5dd7070Spatrick }
1348e5dd7070Spatrick
1349e5dd7070Spatrick return LV;
1350e5dd7070Spatrick }
1351e5dd7070Spatrick
1352e5dd7070Spatrick if (!Var->isStaticLocal())
1353e5dd7070Spatrick return LinkageInfo::none();
1354e5dd7070Spatrick }
1355e5dd7070Spatrick
1356e5dd7070Spatrick ASTContext &Context = D->getASTContext();
1357e5dd7070Spatrick if (!Context.getLangOpts().CPlusPlus)
1358e5dd7070Spatrick return LinkageInfo::none();
1359e5dd7070Spatrick
1360e5dd7070Spatrick const Decl *OuterD = getOutermostFuncOrBlockContext(D);
1361e5dd7070Spatrick if (!OuterD || OuterD->isInvalidDecl())
1362e5dd7070Spatrick return LinkageInfo::none();
1363e5dd7070Spatrick
1364e5dd7070Spatrick LinkageInfo LV;
1365e5dd7070Spatrick if (const auto *BD = dyn_cast<BlockDecl>(OuterD)) {
1366e5dd7070Spatrick if (!BD->getBlockManglingNumber())
1367e5dd7070Spatrick return LinkageInfo::none();
1368e5dd7070Spatrick
1369e5dd7070Spatrick LV = getLVForClosure(BD->getDeclContext()->getRedeclContext(),
1370e5dd7070Spatrick BD->getBlockManglingContextDecl(), computation);
1371e5dd7070Spatrick } else {
1372e5dd7070Spatrick const auto *FD = cast<FunctionDecl>(OuterD);
1373e5dd7070Spatrick if (!FD->isInlined() &&
1374e5dd7070Spatrick !isTemplateInstantiation(FD->getTemplateSpecializationKind()))
1375e5dd7070Spatrick return LinkageInfo::none();
1376e5dd7070Spatrick
1377e5dd7070Spatrick // If a function is hidden by -fvisibility-inlines-hidden option and
1378e5dd7070Spatrick // is not explicitly attributed as a hidden function,
1379e5dd7070Spatrick // we should not make static local variables in the function hidden.
1380e5dd7070Spatrick LV = getLVForDecl(FD, computation);
1381e5dd7070Spatrick if (isa<VarDecl>(D) && useInlineVisibilityHidden(FD) &&
1382a9ac8606Spatrick !LV.isVisibilityExplicit() &&
1383a9ac8606Spatrick !Context.getLangOpts().VisibilityInlinesHiddenStaticLocalVar) {
1384e5dd7070Spatrick assert(cast<VarDecl>(D)->isStaticLocal());
1385e5dd7070Spatrick // If this was an implicitly hidden inline method, check again for
1386e5dd7070Spatrick // explicit visibility on the parent class, and use that for static locals
1387e5dd7070Spatrick // if present.
1388e5dd7070Spatrick if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
1389e5dd7070Spatrick LV = getLVForDecl(MD->getParent(), computation);
1390e5dd7070Spatrick if (!LV.isVisibilityExplicit()) {
1391e5dd7070Spatrick Visibility globalVisibility =
1392e5dd7070Spatrick computation.isValueVisibility()
1393e5dd7070Spatrick ? Context.getLangOpts().getValueVisibilityMode()
1394e5dd7070Spatrick : Context.getLangOpts().getTypeVisibilityMode();
1395e5dd7070Spatrick return LinkageInfo(VisibleNoLinkage, globalVisibility,
1396e5dd7070Spatrick /*visibilityExplicit=*/false);
1397e5dd7070Spatrick }
1398e5dd7070Spatrick }
1399e5dd7070Spatrick }
1400e5dd7070Spatrick if (!isExternallyVisible(LV.getLinkage()))
1401e5dd7070Spatrick return LinkageInfo::none();
1402e5dd7070Spatrick return LinkageInfo(VisibleNoLinkage, LV.getVisibility(),
1403e5dd7070Spatrick LV.isVisibilityExplicit());
1404e5dd7070Spatrick }
1405e5dd7070Spatrick
computeLVForDecl(const NamedDecl * D,LVComputationKind computation,bool IgnoreVarTypeLinkage)1406e5dd7070Spatrick LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
1407e5dd7070Spatrick LVComputationKind computation,
1408e5dd7070Spatrick bool IgnoreVarTypeLinkage) {
1409e5dd7070Spatrick // Internal_linkage attribute overrides other considerations.
1410e5dd7070Spatrick if (D->hasAttr<InternalLinkageAttr>())
1411e5dd7070Spatrick return getInternalLinkageFor(D);
1412e5dd7070Spatrick
1413e5dd7070Spatrick // Objective-C: treat all Objective-C declarations as having external
1414e5dd7070Spatrick // linkage.
1415e5dd7070Spatrick switch (D->getKind()) {
1416e5dd7070Spatrick default:
1417e5dd7070Spatrick break;
1418e5dd7070Spatrick
1419e5dd7070Spatrick // Per C++ [basic.link]p2, only the names of objects, references,
1420e5dd7070Spatrick // functions, types, templates, namespaces, and values ever have linkage.
1421e5dd7070Spatrick //
1422e5dd7070Spatrick // Note that the name of a typedef, namespace alias, using declaration,
1423e5dd7070Spatrick // and so on are not the name of the corresponding type, namespace, or
1424e5dd7070Spatrick // declaration, so they do *not* have linkage.
1425e5dd7070Spatrick case Decl::ImplicitParam:
1426e5dd7070Spatrick case Decl::Label:
1427e5dd7070Spatrick case Decl::NamespaceAlias:
1428e5dd7070Spatrick case Decl::ParmVar:
1429e5dd7070Spatrick case Decl::Using:
1430a9ac8606Spatrick case Decl::UsingEnum:
1431e5dd7070Spatrick case Decl::UsingShadow:
1432e5dd7070Spatrick case Decl::UsingDirective:
1433e5dd7070Spatrick return LinkageInfo::none();
1434e5dd7070Spatrick
1435e5dd7070Spatrick case Decl::EnumConstant:
1436e5dd7070Spatrick // C++ [basic.link]p4: an enumerator has the linkage of its enumeration.
1437e5dd7070Spatrick if (D->getASTContext().getLangOpts().CPlusPlus)
1438e5dd7070Spatrick return getLVForDecl(cast<EnumDecl>(D->getDeclContext()), computation);
1439e5dd7070Spatrick return LinkageInfo::visible_none();
1440e5dd7070Spatrick
1441e5dd7070Spatrick case Decl::Typedef:
1442e5dd7070Spatrick case Decl::TypeAlias:
1443e5dd7070Spatrick // A typedef declaration has linkage if it gives a type a name for
1444e5dd7070Spatrick // linkage purposes.
1445e5dd7070Spatrick if (!cast<TypedefNameDecl>(D)
1446e5dd7070Spatrick ->getAnonDeclWithTypedefName(/*AnyRedecl*/true))
1447e5dd7070Spatrick return LinkageInfo::none();
1448e5dd7070Spatrick break;
1449e5dd7070Spatrick
1450e5dd7070Spatrick case Decl::TemplateTemplateParm: // count these as external
1451e5dd7070Spatrick case Decl::NonTypeTemplateParm:
1452e5dd7070Spatrick case Decl::ObjCAtDefsField:
1453e5dd7070Spatrick case Decl::ObjCCategory:
1454e5dd7070Spatrick case Decl::ObjCCategoryImpl:
1455e5dd7070Spatrick case Decl::ObjCCompatibleAlias:
1456e5dd7070Spatrick case Decl::ObjCImplementation:
1457e5dd7070Spatrick case Decl::ObjCMethod:
1458e5dd7070Spatrick case Decl::ObjCProperty:
1459e5dd7070Spatrick case Decl::ObjCPropertyImpl:
1460e5dd7070Spatrick case Decl::ObjCProtocol:
1461e5dd7070Spatrick return getExternalLinkageFor(D);
1462e5dd7070Spatrick
1463e5dd7070Spatrick case Decl::CXXRecord: {
1464e5dd7070Spatrick const auto *Record = cast<CXXRecordDecl>(D);
1465e5dd7070Spatrick if (Record->isLambda()) {
1466e5dd7070Spatrick if (Record->hasKnownLambdaInternalLinkage() ||
1467e5dd7070Spatrick !Record->getLambdaManglingNumber()) {
1468e5dd7070Spatrick // This lambda has no mangling number, so it's internal.
1469e5dd7070Spatrick return getInternalLinkageFor(D);
1470e5dd7070Spatrick }
1471e5dd7070Spatrick
1472e5dd7070Spatrick return getLVForClosure(
1473ec727ea7Spatrick Record->getDeclContext()->getRedeclContext(),
1474ec727ea7Spatrick Record->getLambdaContextDecl(), computation);
1475e5dd7070Spatrick }
1476e5dd7070Spatrick
1477e5dd7070Spatrick break;
1478e5dd7070Spatrick }
1479a9ac8606Spatrick
1480a9ac8606Spatrick case Decl::TemplateParamObject: {
1481a9ac8606Spatrick // The template parameter object can be referenced from anywhere its type
1482a9ac8606Spatrick // and value can be referenced.
1483a9ac8606Spatrick auto *TPO = cast<TemplateParamObjectDecl>(D);
1484a9ac8606Spatrick LinkageInfo LV = getLVForType(*TPO->getType(), computation);
1485a9ac8606Spatrick LV.merge(getLVForValue(TPO->getValue(), computation));
1486a9ac8606Spatrick return LV;
1487a9ac8606Spatrick }
1488e5dd7070Spatrick }
1489e5dd7070Spatrick
1490e5dd7070Spatrick // Handle linkage for namespace-scope names.
1491e5dd7070Spatrick if (D->getDeclContext()->getRedeclContext()->isFileContext())
1492e5dd7070Spatrick return getLVForNamespaceScopeDecl(D, computation, IgnoreVarTypeLinkage);
1493e5dd7070Spatrick
1494e5dd7070Spatrick // C++ [basic.link]p5:
1495e5dd7070Spatrick // In addition, a member function, static data member, a named
1496e5dd7070Spatrick // class or enumeration of class scope, or an unnamed class or
1497e5dd7070Spatrick // enumeration defined in a class-scope typedef declaration such
1498e5dd7070Spatrick // that the class or enumeration has the typedef name for linkage
1499e5dd7070Spatrick // purposes (7.1.3), has external linkage if the name of the class
1500e5dd7070Spatrick // has external linkage.
1501e5dd7070Spatrick if (D->getDeclContext()->isRecord())
1502e5dd7070Spatrick return getLVForClassMember(D, computation, IgnoreVarTypeLinkage);
1503e5dd7070Spatrick
1504e5dd7070Spatrick // C++ [basic.link]p6:
1505e5dd7070Spatrick // The name of a function declared in block scope and the name of
1506e5dd7070Spatrick // an object declared by a block scope extern declaration have
1507e5dd7070Spatrick // linkage. If there is a visible declaration of an entity with
1508e5dd7070Spatrick // linkage having the same name and type, ignoring entities
1509e5dd7070Spatrick // declared outside the innermost enclosing namespace scope, the
1510e5dd7070Spatrick // block scope declaration declares that same entity and receives
1511e5dd7070Spatrick // the linkage of the previous declaration. If there is more than
1512e5dd7070Spatrick // one such matching entity, the program is ill-formed. Otherwise,
1513e5dd7070Spatrick // if no matching entity is found, the block scope entity receives
1514e5dd7070Spatrick // external linkage.
1515e5dd7070Spatrick if (D->getDeclContext()->isFunctionOrMethod())
1516e5dd7070Spatrick return getLVForLocalDecl(D, computation);
1517e5dd7070Spatrick
1518e5dd7070Spatrick // C++ [basic.link]p6:
1519e5dd7070Spatrick // Names not covered by these rules have no linkage.
1520e5dd7070Spatrick return LinkageInfo::none();
1521e5dd7070Spatrick }
1522e5dd7070Spatrick
1523e5dd7070Spatrick /// getLVForDecl - Get the linkage and visibility for the given declaration.
getLVForDecl(const NamedDecl * D,LVComputationKind computation)1524e5dd7070Spatrick LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D,
1525e5dd7070Spatrick LVComputationKind computation) {
1526e5dd7070Spatrick // Internal_linkage attribute overrides other considerations.
1527e5dd7070Spatrick if (D->hasAttr<InternalLinkageAttr>())
1528e5dd7070Spatrick return getInternalLinkageFor(D);
1529e5dd7070Spatrick
1530e5dd7070Spatrick if (computation.IgnoreAllVisibility && D->hasCachedLinkage())
1531e5dd7070Spatrick return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false);
1532e5dd7070Spatrick
1533*12c85518Srobert if (std::optional<LinkageInfo> LI = lookup(D, computation))
1534e5dd7070Spatrick return *LI;
1535e5dd7070Spatrick
1536e5dd7070Spatrick LinkageInfo LV = computeLVForDecl(D, computation);
1537e5dd7070Spatrick if (D->hasCachedLinkage())
1538e5dd7070Spatrick assert(D->getCachedLinkage() == LV.getLinkage());
1539e5dd7070Spatrick
1540e5dd7070Spatrick D->setCachedLinkage(LV.getLinkage());
1541e5dd7070Spatrick cache(D, computation, LV);
1542e5dd7070Spatrick
1543e5dd7070Spatrick #ifndef NDEBUG
1544e5dd7070Spatrick // In C (because of gnu inline) and in c++ with microsoft extensions an
1545e5dd7070Spatrick // static can follow an extern, so we can have two decls with different
1546e5dd7070Spatrick // linkages.
1547e5dd7070Spatrick const LangOptions &Opts = D->getASTContext().getLangOpts();
1548e5dd7070Spatrick if (!Opts.CPlusPlus || Opts.MicrosoftExt)
1549e5dd7070Spatrick return LV;
1550e5dd7070Spatrick
1551e5dd7070Spatrick // We have just computed the linkage for this decl. By induction we know
1552e5dd7070Spatrick // that all other computed linkages match, check that the one we just
1553e5dd7070Spatrick // computed also does.
1554e5dd7070Spatrick NamedDecl *Old = nullptr;
1555*12c85518Srobert for (auto *I : D->redecls()) {
1556e5dd7070Spatrick auto *T = cast<NamedDecl>(I);
1557e5dd7070Spatrick if (T == D)
1558e5dd7070Spatrick continue;
1559e5dd7070Spatrick if (!T->isInvalidDecl() && T->hasCachedLinkage()) {
1560e5dd7070Spatrick Old = T;
1561e5dd7070Spatrick break;
1562e5dd7070Spatrick }
1563e5dd7070Spatrick }
1564e5dd7070Spatrick assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage());
1565e5dd7070Spatrick #endif
1566e5dd7070Spatrick
1567e5dd7070Spatrick return LV;
1568e5dd7070Spatrick }
1569e5dd7070Spatrick
getDeclLinkageAndVisibility(const NamedDecl * D)1570e5dd7070Spatrick LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) {
1571a9ac8606Spatrick NamedDecl::ExplicitVisibilityKind EK = usesTypeVisibility(D)
1572e5dd7070Spatrick ? NamedDecl::VisibilityForType
1573a9ac8606Spatrick : NamedDecl::VisibilityForValue;
1574a9ac8606Spatrick LVComputationKind CK(EK);
1575a9ac8606Spatrick return getLVForDecl(D, D->getASTContext().getLangOpts().IgnoreXCOFFVisibility
1576a9ac8606Spatrick ? CK.forLinkageOnly()
1577a9ac8606Spatrick : CK);
1578e5dd7070Spatrick }
1579e5dd7070Spatrick
getOwningModuleForLinkage(bool IgnoreLinkage) const1580e5dd7070Spatrick Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const {
1581*12c85518Srobert if (isa<NamespaceDecl>(this))
1582*12c85518Srobert // Namespaces never have module linkage. It is the entities within them
1583*12c85518Srobert // that [may] do.
1584*12c85518Srobert return nullptr;
1585*12c85518Srobert
1586e5dd7070Spatrick Module *M = getOwningModule();
1587e5dd7070Spatrick if (!M)
1588e5dd7070Spatrick return nullptr;
1589e5dd7070Spatrick
1590e5dd7070Spatrick switch (M->Kind) {
1591e5dd7070Spatrick case Module::ModuleMapModule:
1592e5dd7070Spatrick // Module map modules have no special linkage semantics.
1593e5dd7070Spatrick return nullptr;
1594e5dd7070Spatrick
1595e5dd7070Spatrick case Module::ModuleInterfaceUnit:
1596*12c85518Srobert case Module::ModulePartitionInterface:
1597*12c85518Srobert case Module::ModulePartitionImplementation:
1598e5dd7070Spatrick return M;
1599e5dd7070Spatrick
1600*12c85518Srobert case Module::ModuleHeaderUnit:
1601e5dd7070Spatrick case Module::GlobalModuleFragment: {
1602e5dd7070Spatrick // External linkage declarations in the global module have no owning module
1603e5dd7070Spatrick // for linkage purposes. But internal linkage declarations in the global
1604e5dd7070Spatrick // module fragment of a particular module are owned by that module for
1605e5dd7070Spatrick // linkage purposes.
1606*12c85518Srobert // FIXME: p1815 removes the need for this distinction -- there are no
1607*12c85518Srobert // internal linkage declarations that need to be referred to from outside
1608*12c85518Srobert // this TU.
1609e5dd7070Spatrick if (IgnoreLinkage)
1610e5dd7070Spatrick return nullptr;
1611e5dd7070Spatrick bool InternalLinkage;
1612e5dd7070Spatrick if (auto *ND = dyn_cast<NamedDecl>(this))
1613e5dd7070Spatrick InternalLinkage = !ND->hasExternalFormalLinkage();
1614*12c85518Srobert else
1615*12c85518Srobert InternalLinkage = isInAnonymousNamespace();
1616*12c85518Srobert return InternalLinkage ? M->Kind == Module::ModuleHeaderUnit ? M : M->Parent
1617*12c85518Srobert : nullptr;
1618e5dd7070Spatrick }
1619e5dd7070Spatrick
1620e5dd7070Spatrick case Module::PrivateModuleFragment:
1621e5dd7070Spatrick // The private module fragment is part of its containing module for linkage
1622e5dd7070Spatrick // purposes.
1623e5dd7070Spatrick return M->Parent;
1624e5dd7070Spatrick }
1625e5dd7070Spatrick
1626e5dd7070Spatrick llvm_unreachable("unknown module kind");
1627e5dd7070Spatrick }
1628e5dd7070Spatrick
printName(raw_ostream & OS,const PrintingPolicy &) const1629*12c85518Srobert void NamedDecl::printName(raw_ostream &OS, const PrintingPolicy&) const {
1630*12c85518Srobert OS << Name;
1631*12c85518Srobert }
1632*12c85518Srobert
printName(raw_ostream & OS) const1633*12c85518Srobert void NamedDecl::printName(raw_ostream &OS) const {
1634*12c85518Srobert printName(OS, getASTContext().getPrintingPolicy());
1635e5dd7070Spatrick }
1636e5dd7070Spatrick
getQualifiedNameAsString() const1637e5dd7070Spatrick std::string NamedDecl::getQualifiedNameAsString() const {
1638e5dd7070Spatrick std::string QualName;
1639e5dd7070Spatrick llvm::raw_string_ostream OS(QualName);
1640e5dd7070Spatrick printQualifiedName(OS, getASTContext().getPrintingPolicy());
1641*12c85518Srobert return QualName;
1642e5dd7070Spatrick }
1643e5dd7070Spatrick
printQualifiedName(raw_ostream & OS) const1644e5dd7070Spatrick void NamedDecl::printQualifiedName(raw_ostream &OS) const {
1645e5dd7070Spatrick printQualifiedName(OS, getASTContext().getPrintingPolicy());
1646e5dd7070Spatrick }
1647e5dd7070Spatrick
printQualifiedName(raw_ostream & OS,const PrintingPolicy & P) const1648e5dd7070Spatrick void NamedDecl::printQualifiedName(raw_ostream &OS,
1649e5dd7070Spatrick const PrintingPolicy &P) const {
1650e5dd7070Spatrick if (getDeclContext()->isFunctionOrMethod()) {
1651e5dd7070Spatrick // We do not print '(anonymous)' for function parameters without name.
1652*12c85518Srobert printName(OS, P);
1653e5dd7070Spatrick return;
1654e5dd7070Spatrick }
1655e5dd7070Spatrick printNestedNameSpecifier(OS, P);
1656ec727ea7Spatrick if (getDeclName())
1657e5dd7070Spatrick OS << *this;
1658ec727ea7Spatrick else {
1659ec727ea7Spatrick // Give the printName override a chance to pick a different name before we
1660ec727ea7Spatrick // fall back to "(anonymous)".
1661ec727ea7Spatrick SmallString<64> NameBuffer;
1662ec727ea7Spatrick llvm::raw_svector_ostream NameOS(NameBuffer);
1663*12c85518Srobert printName(NameOS, P);
1664ec727ea7Spatrick if (NameBuffer.empty())
1665e5dd7070Spatrick OS << "(anonymous)";
1666ec727ea7Spatrick else
1667ec727ea7Spatrick OS << NameBuffer;
1668ec727ea7Spatrick }
1669e5dd7070Spatrick }
1670e5dd7070Spatrick
printNestedNameSpecifier(raw_ostream & OS) const1671e5dd7070Spatrick void NamedDecl::printNestedNameSpecifier(raw_ostream &OS) const {
1672e5dd7070Spatrick printNestedNameSpecifier(OS, getASTContext().getPrintingPolicy());
1673e5dd7070Spatrick }
1674e5dd7070Spatrick
printNestedNameSpecifier(raw_ostream & OS,const PrintingPolicy & P) const1675e5dd7070Spatrick void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
1676e5dd7070Spatrick const PrintingPolicy &P) const {
1677e5dd7070Spatrick const DeclContext *Ctx = getDeclContext();
1678e5dd7070Spatrick
1679e5dd7070Spatrick // For ObjC methods and properties, look through categories and use the
1680e5dd7070Spatrick // interface as context.
1681ec727ea7Spatrick if (auto *MD = dyn_cast<ObjCMethodDecl>(this)) {
1682e5dd7070Spatrick if (auto *ID = MD->getClassInterface())
1683e5dd7070Spatrick Ctx = ID;
1684ec727ea7Spatrick } else if (auto *PD = dyn_cast<ObjCPropertyDecl>(this)) {
1685e5dd7070Spatrick if (auto *MD = PD->getGetterMethodDecl())
1686e5dd7070Spatrick if (auto *ID = MD->getClassInterface())
1687e5dd7070Spatrick Ctx = ID;
1688ec727ea7Spatrick } else if (auto *ID = dyn_cast<ObjCIvarDecl>(this)) {
1689ec727ea7Spatrick if (auto *CI = ID->getContainingInterface())
1690ec727ea7Spatrick Ctx = CI;
1691e5dd7070Spatrick }
1692e5dd7070Spatrick
1693e5dd7070Spatrick if (Ctx->isFunctionOrMethod())
1694e5dd7070Spatrick return;
1695e5dd7070Spatrick
1696e5dd7070Spatrick using ContextsTy = SmallVector<const DeclContext *, 8>;
1697e5dd7070Spatrick ContextsTy Contexts;
1698e5dd7070Spatrick
1699e5dd7070Spatrick // Collect named contexts.
1700a9ac8606Spatrick DeclarationName NameInScope = getDeclName();
1701a9ac8606Spatrick for (; Ctx; Ctx = Ctx->getParent()) {
1702a9ac8606Spatrick // Suppress anonymous namespace if requested.
1703a9ac8606Spatrick if (P.SuppressUnwrittenScope && isa<NamespaceDecl>(Ctx) &&
1704a9ac8606Spatrick cast<NamespaceDecl>(Ctx)->isAnonymousNamespace())
1705a9ac8606Spatrick continue;
1706a9ac8606Spatrick
1707a9ac8606Spatrick // Suppress inline namespace if it doesn't make the result ambiguous.
1708a9ac8606Spatrick if (P.SuppressInlineNamespace && Ctx->isInlineNamespace() && NameInScope &&
1709a9ac8606Spatrick cast<NamespaceDecl>(Ctx)->isRedundantInlineQualifierFor(NameInScope))
1710a9ac8606Spatrick continue;
1711a9ac8606Spatrick
1712a9ac8606Spatrick // Skip non-named contexts such as linkage specifications and ExportDecls.
1713a9ac8606Spatrick const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx);
1714a9ac8606Spatrick if (!ND)
1715a9ac8606Spatrick continue;
1716a9ac8606Spatrick
1717e5dd7070Spatrick Contexts.push_back(Ctx);
1718a9ac8606Spatrick NameInScope = ND->getDeclName();
1719e5dd7070Spatrick }
1720e5dd7070Spatrick
1721*12c85518Srobert for (const DeclContext *DC : llvm::reverse(Contexts)) {
1722e5dd7070Spatrick if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
1723e5dd7070Spatrick OS << Spec->getName();
1724e5dd7070Spatrick const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
1725a9ac8606Spatrick printTemplateArgumentList(
1726a9ac8606Spatrick OS, TemplateArgs.asArray(), P,
1727a9ac8606Spatrick Spec->getSpecializedTemplate()->getTemplateParameters());
1728e5dd7070Spatrick } else if (const auto *ND = dyn_cast<NamespaceDecl>(DC)) {
1729e5dd7070Spatrick if (ND->isAnonymousNamespace()) {
1730e5dd7070Spatrick OS << (P.MSVCFormatting ? "`anonymous namespace\'"
1731e5dd7070Spatrick : "(anonymous namespace)");
1732e5dd7070Spatrick }
1733e5dd7070Spatrick else
1734e5dd7070Spatrick OS << *ND;
1735e5dd7070Spatrick } else if (const auto *RD = dyn_cast<RecordDecl>(DC)) {
1736e5dd7070Spatrick if (!RD->getIdentifier())
1737e5dd7070Spatrick OS << "(anonymous " << RD->getKindName() << ')';
1738e5dd7070Spatrick else
1739e5dd7070Spatrick OS << *RD;
1740e5dd7070Spatrick } else if (const auto *FD = dyn_cast<FunctionDecl>(DC)) {
1741e5dd7070Spatrick const FunctionProtoType *FT = nullptr;
1742e5dd7070Spatrick if (FD->hasWrittenPrototype())
1743e5dd7070Spatrick FT = dyn_cast<FunctionProtoType>(FD->getType()->castAs<FunctionType>());
1744e5dd7070Spatrick
1745e5dd7070Spatrick OS << *FD << '(';
1746e5dd7070Spatrick if (FT) {
1747e5dd7070Spatrick unsigned NumParams = FD->getNumParams();
1748e5dd7070Spatrick for (unsigned i = 0; i < NumParams; ++i) {
1749e5dd7070Spatrick if (i)
1750e5dd7070Spatrick OS << ", ";
1751e5dd7070Spatrick OS << FD->getParamDecl(i)->getType().stream(P);
1752e5dd7070Spatrick }
1753e5dd7070Spatrick
1754e5dd7070Spatrick if (FT->isVariadic()) {
1755e5dd7070Spatrick if (NumParams > 0)
1756e5dd7070Spatrick OS << ", ";
1757e5dd7070Spatrick OS << "...";
1758e5dd7070Spatrick }
1759e5dd7070Spatrick }
1760e5dd7070Spatrick OS << ')';
1761e5dd7070Spatrick } else if (const auto *ED = dyn_cast<EnumDecl>(DC)) {
1762e5dd7070Spatrick // C++ [dcl.enum]p10: Each enum-name and each unscoped
1763e5dd7070Spatrick // enumerator is declared in the scope that immediately contains
1764e5dd7070Spatrick // the enum-specifier. Each scoped enumerator is declared in the
1765e5dd7070Spatrick // scope of the enumeration.
1766e5dd7070Spatrick // For the case of unscoped enumerator, do not include in the qualified
1767e5dd7070Spatrick // name any information about its enum enclosing scope, as its visibility
1768e5dd7070Spatrick // is global.
1769e5dd7070Spatrick if (ED->isScoped())
1770e5dd7070Spatrick OS << *ED;
1771e5dd7070Spatrick else
1772e5dd7070Spatrick continue;
1773e5dd7070Spatrick } else {
1774e5dd7070Spatrick OS << *cast<NamedDecl>(DC);
1775e5dd7070Spatrick }
1776e5dd7070Spatrick OS << "::";
1777e5dd7070Spatrick }
1778e5dd7070Spatrick }
1779e5dd7070Spatrick
getNameForDiagnostic(raw_ostream & OS,const PrintingPolicy & Policy,bool Qualified) const1780e5dd7070Spatrick void NamedDecl::getNameForDiagnostic(raw_ostream &OS,
1781e5dd7070Spatrick const PrintingPolicy &Policy,
1782e5dd7070Spatrick bool Qualified) const {
1783e5dd7070Spatrick if (Qualified)
1784e5dd7070Spatrick printQualifiedName(OS, Policy);
1785e5dd7070Spatrick else
1786*12c85518Srobert printName(OS, Policy);
1787e5dd7070Spatrick }
1788e5dd7070Spatrick
isRedeclarableImpl(Redeclarable<T> *)1789e5dd7070Spatrick template<typename T> static bool isRedeclarableImpl(Redeclarable<T> *) {
1790e5dd7070Spatrick return true;
1791e5dd7070Spatrick }
isRedeclarableImpl(...)1792e5dd7070Spatrick static bool isRedeclarableImpl(...) { return false; }
isRedeclarable(Decl::Kind K)1793e5dd7070Spatrick static bool isRedeclarable(Decl::Kind K) {
1794e5dd7070Spatrick switch (K) {
1795e5dd7070Spatrick #define DECL(Type, Base) \
1796e5dd7070Spatrick case Decl::Type: \
1797e5dd7070Spatrick return isRedeclarableImpl((Type##Decl *)nullptr);
1798e5dd7070Spatrick #define ABSTRACT_DECL(DECL)
1799e5dd7070Spatrick #include "clang/AST/DeclNodes.inc"
1800e5dd7070Spatrick }
1801e5dd7070Spatrick llvm_unreachable("unknown decl kind");
1802e5dd7070Spatrick }
1803e5dd7070Spatrick
declarationReplaces(NamedDecl * OldD,bool IsKnownNewer) const1804e5dd7070Spatrick bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
1805e5dd7070Spatrick assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
1806e5dd7070Spatrick
1807e5dd7070Spatrick // Never replace one imported declaration with another; we need both results
1808e5dd7070Spatrick // when re-exporting.
1809e5dd7070Spatrick if (OldD->isFromASTFile() && isFromASTFile())
1810e5dd7070Spatrick return false;
1811e5dd7070Spatrick
1812e5dd7070Spatrick // A kind mismatch implies that the declaration is not replaced.
1813e5dd7070Spatrick if (OldD->getKind() != getKind())
1814e5dd7070Spatrick return false;
1815e5dd7070Spatrick
1816e5dd7070Spatrick // For method declarations, we never replace. (Why?)
1817e5dd7070Spatrick if (isa<ObjCMethodDecl>(this))
1818e5dd7070Spatrick return false;
1819e5dd7070Spatrick
1820e5dd7070Spatrick // For parameters, pick the newer one. This is either an error or (in
1821e5dd7070Spatrick // Objective-C) permitted as an extension.
1822e5dd7070Spatrick if (isa<ParmVarDecl>(this))
1823e5dd7070Spatrick return true;
1824e5dd7070Spatrick
1825e5dd7070Spatrick // Inline namespaces can give us two declarations with the same
1826e5dd7070Spatrick // name and kind in the same scope but different contexts; we should
1827e5dd7070Spatrick // keep both declarations in this case.
1828e5dd7070Spatrick if (!this->getDeclContext()->getRedeclContext()->Equals(
1829e5dd7070Spatrick OldD->getDeclContext()->getRedeclContext()))
1830e5dd7070Spatrick return false;
1831e5dd7070Spatrick
1832e5dd7070Spatrick // Using declarations can be replaced if they import the same name from the
1833e5dd7070Spatrick // same context.
1834e5dd7070Spatrick if (auto *UD = dyn_cast<UsingDecl>(this)) {
1835e5dd7070Spatrick ASTContext &Context = getASTContext();
1836e5dd7070Spatrick return Context.getCanonicalNestedNameSpecifier(UD->getQualifier()) ==
1837e5dd7070Spatrick Context.getCanonicalNestedNameSpecifier(
1838e5dd7070Spatrick cast<UsingDecl>(OldD)->getQualifier());
1839e5dd7070Spatrick }
1840e5dd7070Spatrick if (auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(this)) {
1841e5dd7070Spatrick ASTContext &Context = getASTContext();
1842e5dd7070Spatrick return Context.getCanonicalNestedNameSpecifier(UUVD->getQualifier()) ==
1843e5dd7070Spatrick Context.getCanonicalNestedNameSpecifier(
1844e5dd7070Spatrick cast<UnresolvedUsingValueDecl>(OldD)->getQualifier());
1845e5dd7070Spatrick }
1846e5dd7070Spatrick
1847e5dd7070Spatrick if (isRedeclarable(getKind())) {
1848e5dd7070Spatrick if (getCanonicalDecl() != OldD->getCanonicalDecl())
1849e5dd7070Spatrick return false;
1850e5dd7070Spatrick
1851e5dd7070Spatrick if (IsKnownNewer)
1852e5dd7070Spatrick return true;
1853e5dd7070Spatrick
1854e5dd7070Spatrick // Check whether this is actually newer than OldD. We want to keep the
1855e5dd7070Spatrick // newer declaration. This loop will usually only iterate once, because
1856e5dd7070Spatrick // OldD is usually the previous declaration.
1857*12c85518Srobert for (auto *D : redecls()) {
1858e5dd7070Spatrick if (D == OldD)
1859e5dd7070Spatrick break;
1860e5dd7070Spatrick
1861e5dd7070Spatrick // If we reach the canonical declaration, then OldD is not actually older
1862e5dd7070Spatrick // than this one.
1863e5dd7070Spatrick //
1864e5dd7070Spatrick // FIXME: In this case, we should not add this decl to the lookup table.
1865e5dd7070Spatrick if (D->isCanonicalDecl())
1866e5dd7070Spatrick return false;
1867e5dd7070Spatrick }
1868e5dd7070Spatrick
1869e5dd7070Spatrick // It's a newer declaration of the same kind of declaration in the same
1870e5dd7070Spatrick // scope: we want this decl instead of the existing one.
1871e5dd7070Spatrick return true;
1872e5dd7070Spatrick }
1873e5dd7070Spatrick
1874e5dd7070Spatrick // In all other cases, we need to keep both declarations in case they have
1875e5dd7070Spatrick // different visibility. Any attempt to use the name will result in an
1876e5dd7070Spatrick // ambiguity if more than one is visible.
1877e5dd7070Spatrick return false;
1878e5dd7070Spatrick }
1879e5dd7070Spatrick
hasLinkage() const1880e5dd7070Spatrick bool NamedDecl::hasLinkage() const {
1881e5dd7070Spatrick return getFormalLinkage() != NoLinkage;
1882e5dd7070Spatrick }
1883e5dd7070Spatrick
getUnderlyingDeclImpl()1884e5dd7070Spatrick NamedDecl *NamedDecl::getUnderlyingDeclImpl() {
1885e5dd7070Spatrick NamedDecl *ND = this;
1886*12c85518Srobert if (auto *UD = dyn_cast<UsingShadowDecl>(ND))
1887e5dd7070Spatrick ND = UD->getTargetDecl();
1888e5dd7070Spatrick
1889e5dd7070Spatrick if (auto *AD = dyn_cast<ObjCCompatibleAliasDecl>(ND))
1890e5dd7070Spatrick return AD->getClassInterface();
1891e5dd7070Spatrick
1892e5dd7070Spatrick if (auto *AD = dyn_cast<NamespaceAliasDecl>(ND))
1893e5dd7070Spatrick return AD->getNamespace();
1894e5dd7070Spatrick
1895e5dd7070Spatrick return ND;
1896e5dd7070Spatrick }
1897e5dd7070Spatrick
isCXXInstanceMember() const1898e5dd7070Spatrick bool NamedDecl::isCXXInstanceMember() const {
1899e5dd7070Spatrick if (!isCXXClassMember())
1900e5dd7070Spatrick return false;
1901e5dd7070Spatrick
1902e5dd7070Spatrick const NamedDecl *D = this;
1903e5dd7070Spatrick if (isa<UsingShadowDecl>(D))
1904e5dd7070Spatrick D = cast<UsingShadowDecl>(D)->getTargetDecl();
1905e5dd7070Spatrick
1906e5dd7070Spatrick if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<MSPropertyDecl>(D))
1907e5dd7070Spatrick return true;
1908e5dd7070Spatrick if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()))
1909e5dd7070Spatrick return MD->isInstance();
1910e5dd7070Spatrick return false;
1911e5dd7070Spatrick }
1912e5dd7070Spatrick
1913e5dd7070Spatrick //===----------------------------------------------------------------------===//
1914e5dd7070Spatrick // DeclaratorDecl Implementation
1915e5dd7070Spatrick //===----------------------------------------------------------------------===//
1916e5dd7070Spatrick
1917e5dd7070Spatrick template <typename DeclT>
getTemplateOrInnerLocStart(const DeclT * decl)1918e5dd7070Spatrick static SourceLocation getTemplateOrInnerLocStart(const DeclT *decl) {
1919e5dd7070Spatrick if (decl->getNumTemplateParameterLists() > 0)
1920e5dd7070Spatrick return decl->getTemplateParameterList(0)->getTemplateLoc();
1921e5dd7070Spatrick return decl->getInnerLocStart();
1922e5dd7070Spatrick }
1923e5dd7070Spatrick
getTypeSpecStartLoc() const1924e5dd7070Spatrick SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
1925e5dd7070Spatrick TypeSourceInfo *TSI = getTypeSourceInfo();
1926e5dd7070Spatrick if (TSI) return TSI->getTypeLoc().getBeginLoc();
1927e5dd7070Spatrick return SourceLocation();
1928e5dd7070Spatrick }
1929e5dd7070Spatrick
getTypeSpecEndLoc() const1930e5dd7070Spatrick SourceLocation DeclaratorDecl::getTypeSpecEndLoc() const {
1931e5dd7070Spatrick TypeSourceInfo *TSI = getTypeSourceInfo();
1932e5dd7070Spatrick if (TSI) return TSI->getTypeLoc().getEndLoc();
1933e5dd7070Spatrick return SourceLocation();
1934e5dd7070Spatrick }
1935e5dd7070Spatrick
setQualifierInfo(NestedNameSpecifierLoc QualifierLoc)1936e5dd7070Spatrick void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
1937e5dd7070Spatrick if (QualifierLoc) {
1938e5dd7070Spatrick // Make sure the extended decl info is allocated.
1939e5dd7070Spatrick if (!hasExtInfo()) {
1940e5dd7070Spatrick // Save (non-extended) type source info pointer.
1941e5dd7070Spatrick auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
1942e5dd7070Spatrick // Allocate external info struct.
1943e5dd7070Spatrick DeclInfo = new (getASTContext()) ExtInfo;
1944e5dd7070Spatrick // Restore savedTInfo into (extended) decl info.
1945e5dd7070Spatrick getExtInfo()->TInfo = savedTInfo;
1946e5dd7070Spatrick }
1947e5dd7070Spatrick // Set qualifier info.
1948e5dd7070Spatrick getExtInfo()->QualifierLoc = QualifierLoc;
1949e5dd7070Spatrick } else if (hasExtInfo()) {
1950e5dd7070Spatrick // Here Qualifier == 0, i.e., we are removing the qualifier (if any).
1951e5dd7070Spatrick getExtInfo()->QualifierLoc = QualifierLoc;
1952e5dd7070Spatrick }
1953e5dd7070Spatrick }
1954e5dd7070Spatrick
setTrailingRequiresClause(Expr * TrailingRequiresClause)1955e5dd7070Spatrick void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) {
1956e5dd7070Spatrick assert(TrailingRequiresClause);
1957e5dd7070Spatrick // Make sure the extended decl info is allocated.
1958e5dd7070Spatrick if (!hasExtInfo()) {
1959e5dd7070Spatrick // Save (non-extended) type source info pointer.
1960e5dd7070Spatrick auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
1961e5dd7070Spatrick // Allocate external info struct.
1962e5dd7070Spatrick DeclInfo = new (getASTContext()) ExtInfo;
1963e5dd7070Spatrick // Restore savedTInfo into (extended) decl info.
1964e5dd7070Spatrick getExtInfo()->TInfo = savedTInfo;
1965e5dd7070Spatrick }
1966e5dd7070Spatrick // Set requires clause info.
1967e5dd7070Spatrick getExtInfo()->TrailingRequiresClause = TrailingRequiresClause;
1968e5dd7070Spatrick }
1969e5dd7070Spatrick
setTemplateParameterListsInfo(ASTContext & Context,ArrayRef<TemplateParameterList * > TPLists)1970e5dd7070Spatrick void DeclaratorDecl::setTemplateParameterListsInfo(
1971e5dd7070Spatrick ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
1972e5dd7070Spatrick assert(!TPLists.empty());
1973e5dd7070Spatrick // Make sure the extended decl info is allocated.
1974e5dd7070Spatrick if (!hasExtInfo()) {
1975e5dd7070Spatrick // Save (non-extended) type source info pointer.
1976e5dd7070Spatrick auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
1977e5dd7070Spatrick // Allocate external info struct.
1978e5dd7070Spatrick DeclInfo = new (getASTContext()) ExtInfo;
1979e5dd7070Spatrick // Restore savedTInfo into (extended) decl info.
1980e5dd7070Spatrick getExtInfo()->TInfo = savedTInfo;
1981e5dd7070Spatrick }
1982e5dd7070Spatrick // Set the template parameter lists info.
1983e5dd7070Spatrick getExtInfo()->setTemplateParameterListsInfo(Context, TPLists);
1984e5dd7070Spatrick }
1985e5dd7070Spatrick
getOuterLocStart() const1986e5dd7070Spatrick SourceLocation DeclaratorDecl::getOuterLocStart() const {
1987e5dd7070Spatrick return getTemplateOrInnerLocStart(this);
1988e5dd7070Spatrick }
1989e5dd7070Spatrick
1990e5dd7070Spatrick // Helper function: returns true if QT is or contains a type
1991e5dd7070Spatrick // having a postfix component.
typeIsPostfix(QualType QT)1992e5dd7070Spatrick static bool typeIsPostfix(QualType QT) {
1993e5dd7070Spatrick while (true) {
1994e5dd7070Spatrick const Type* T = QT.getTypePtr();
1995e5dd7070Spatrick switch (T->getTypeClass()) {
1996e5dd7070Spatrick default:
1997e5dd7070Spatrick return false;
1998e5dd7070Spatrick case Type::Pointer:
1999e5dd7070Spatrick QT = cast<PointerType>(T)->getPointeeType();
2000e5dd7070Spatrick break;
2001e5dd7070Spatrick case Type::BlockPointer:
2002e5dd7070Spatrick QT = cast<BlockPointerType>(T)->getPointeeType();
2003e5dd7070Spatrick break;
2004e5dd7070Spatrick case Type::MemberPointer:
2005e5dd7070Spatrick QT = cast<MemberPointerType>(T)->getPointeeType();
2006e5dd7070Spatrick break;
2007e5dd7070Spatrick case Type::LValueReference:
2008e5dd7070Spatrick case Type::RValueReference:
2009e5dd7070Spatrick QT = cast<ReferenceType>(T)->getPointeeType();
2010e5dd7070Spatrick break;
2011e5dd7070Spatrick case Type::PackExpansion:
2012e5dd7070Spatrick QT = cast<PackExpansionType>(T)->getPattern();
2013e5dd7070Spatrick break;
2014e5dd7070Spatrick case Type::Paren:
2015e5dd7070Spatrick case Type::ConstantArray:
2016e5dd7070Spatrick case Type::DependentSizedArray:
2017e5dd7070Spatrick case Type::IncompleteArray:
2018e5dd7070Spatrick case Type::VariableArray:
2019e5dd7070Spatrick case Type::FunctionProto:
2020e5dd7070Spatrick case Type::FunctionNoProto:
2021e5dd7070Spatrick return true;
2022e5dd7070Spatrick }
2023e5dd7070Spatrick }
2024e5dd7070Spatrick }
2025e5dd7070Spatrick
getSourceRange() const2026e5dd7070Spatrick SourceRange DeclaratorDecl::getSourceRange() const {
2027e5dd7070Spatrick SourceLocation RangeEnd = getLocation();
2028e5dd7070Spatrick if (TypeSourceInfo *TInfo = getTypeSourceInfo()) {
2029e5dd7070Spatrick // If the declaration has no name or the type extends past the name take the
2030e5dd7070Spatrick // end location of the type.
2031e5dd7070Spatrick if (!getDeclName() || typeIsPostfix(TInfo->getType()))
2032e5dd7070Spatrick RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd();
2033e5dd7070Spatrick }
2034e5dd7070Spatrick return SourceRange(getOuterLocStart(), RangeEnd);
2035e5dd7070Spatrick }
2036e5dd7070Spatrick
setTemplateParameterListsInfo(ASTContext & Context,ArrayRef<TemplateParameterList * > TPLists)2037e5dd7070Spatrick void QualifierInfo::setTemplateParameterListsInfo(
2038e5dd7070Spatrick ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
2039e5dd7070Spatrick // Free previous template parameters (if any).
2040e5dd7070Spatrick if (NumTemplParamLists > 0) {
2041e5dd7070Spatrick Context.Deallocate(TemplParamLists);
2042e5dd7070Spatrick TemplParamLists = nullptr;
2043e5dd7070Spatrick NumTemplParamLists = 0;
2044e5dd7070Spatrick }
2045e5dd7070Spatrick // Set info on matched template parameter lists (if any).
2046e5dd7070Spatrick if (!TPLists.empty()) {
2047e5dd7070Spatrick TemplParamLists = new (Context) TemplateParameterList *[TPLists.size()];
2048e5dd7070Spatrick NumTemplParamLists = TPLists.size();
2049e5dd7070Spatrick std::copy(TPLists.begin(), TPLists.end(), TemplParamLists);
2050e5dd7070Spatrick }
2051e5dd7070Spatrick }
2052e5dd7070Spatrick
2053e5dd7070Spatrick //===----------------------------------------------------------------------===//
2054e5dd7070Spatrick // VarDecl Implementation
2055e5dd7070Spatrick //===----------------------------------------------------------------------===//
2056e5dd7070Spatrick
getStorageClassSpecifierString(StorageClass SC)2057e5dd7070Spatrick const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) {
2058e5dd7070Spatrick switch (SC) {
2059e5dd7070Spatrick case SC_None: break;
2060e5dd7070Spatrick case SC_Auto: return "auto";
2061e5dd7070Spatrick case SC_Extern: return "extern";
2062e5dd7070Spatrick case SC_PrivateExtern: return "__private_extern__";
2063e5dd7070Spatrick case SC_Register: return "register";
2064e5dd7070Spatrick case SC_Static: return "static";
2065e5dd7070Spatrick }
2066e5dd7070Spatrick
2067e5dd7070Spatrick llvm_unreachable("Invalid storage class");
2068e5dd7070Spatrick }
2069e5dd7070Spatrick
VarDecl(Kind DK,ASTContext & C,DeclContext * DC,SourceLocation StartLoc,SourceLocation IdLoc,const IdentifierInfo * Id,QualType T,TypeSourceInfo * TInfo,StorageClass SC)2070e5dd7070Spatrick VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC,
2071e5dd7070Spatrick SourceLocation StartLoc, SourceLocation IdLoc,
2072*12c85518Srobert const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
2073e5dd7070Spatrick StorageClass SC)
2074e5dd7070Spatrick : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
2075e5dd7070Spatrick redeclarable_base(C) {
2076e5dd7070Spatrick static_assert(sizeof(VarDeclBitfields) <= sizeof(unsigned),
2077e5dd7070Spatrick "VarDeclBitfields too large!");
2078e5dd7070Spatrick static_assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned),
2079e5dd7070Spatrick "ParmVarDeclBitfields too large!");
2080e5dd7070Spatrick static_assert(sizeof(NonParmVarDeclBitfields) <= sizeof(unsigned),
2081e5dd7070Spatrick "NonParmVarDeclBitfields too large!");
2082e5dd7070Spatrick AllBits = 0;
2083e5dd7070Spatrick VarDeclBits.SClass = SC;
2084e5dd7070Spatrick // Everything else is implicitly initialized to false.
2085e5dd7070Spatrick }
2086e5dd7070Spatrick
Create(ASTContext & C,DeclContext * DC,SourceLocation StartL,SourceLocation IdL,const IdentifierInfo * Id,QualType T,TypeSourceInfo * TInfo,StorageClass S)2087*12c85518Srobert VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartL,
2088*12c85518Srobert SourceLocation IdL, const IdentifierInfo *Id,
2089*12c85518Srobert QualType T, TypeSourceInfo *TInfo, StorageClass S) {
2090e5dd7070Spatrick return new (C, DC) VarDecl(Var, C, DC, StartL, IdL, Id, T, TInfo, S);
2091e5dd7070Spatrick }
2092e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID)2093e5dd7070Spatrick VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
2094e5dd7070Spatrick return new (C, ID)
2095e5dd7070Spatrick VarDecl(Var, C, nullptr, SourceLocation(), SourceLocation(), nullptr,
2096e5dd7070Spatrick QualType(), nullptr, SC_None);
2097e5dd7070Spatrick }
2098e5dd7070Spatrick
setStorageClass(StorageClass SC)2099e5dd7070Spatrick void VarDecl::setStorageClass(StorageClass SC) {
2100e5dd7070Spatrick assert(isLegalForVariable(SC));
2101e5dd7070Spatrick VarDeclBits.SClass = SC;
2102e5dd7070Spatrick }
2103e5dd7070Spatrick
getTLSKind() const2104e5dd7070Spatrick VarDecl::TLSKind VarDecl::getTLSKind() const {
2105e5dd7070Spatrick switch (VarDeclBits.TSCSpec) {
2106e5dd7070Spatrick case TSCS_unspecified:
2107e5dd7070Spatrick if (!hasAttr<ThreadAttr>() &&
2108e5dd7070Spatrick !(getASTContext().getLangOpts().OpenMPUseTLS &&
2109e5dd7070Spatrick getASTContext().getTargetInfo().isTLSSupported() &&
2110e5dd7070Spatrick hasAttr<OMPThreadPrivateDeclAttr>()))
2111e5dd7070Spatrick return TLS_None;
2112e5dd7070Spatrick return ((getASTContext().getLangOpts().isCompatibleWithMSVC(
2113e5dd7070Spatrick LangOptions::MSVC2015)) ||
2114e5dd7070Spatrick hasAttr<OMPThreadPrivateDeclAttr>())
2115e5dd7070Spatrick ? TLS_Dynamic
2116e5dd7070Spatrick : TLS_Static;
2117e5dd7070Spatrick case TSCS___thread: // Fall through.
2118e5dd7070Spatrick case TSCS__Thread_local:
2119e5dd7070Spatrick return TLS_Static;
2120e5dd7070Spatrick case TSCS_thread_local:
2121e5dd7070Spatrick return TLS_Dynamic;
2122e5dd7070Spatrick }
2123e5dd7070Spatrick llvm_unreachable("Unknown thread storage class specifier!");
2124e5dd7070Spatrick }
2125e5dd7070Spatrick
getSourceRange() const2126e5dd7070Spatrick SourceRange VarDecl::getSourceRange() const {
2127e5dd7070Spatrick if (const Expr *Init = getInit()) {
2128e5dd7070Spatrick SourceLocation InitEnd = Init->getEndLoc();
2129e5dd7070Spatrick // If Init is implicit, ignore its source range and fallback on
2130e5dd7070Spatrick // DeclaratorDecl::getSourceRange() to handle postfix elements.
2131e5dd7070Spatrick if (InitEnd.isValid() && InitEnd != getLocation())
2132e5dd7070Spatrick return SourceRange(getOuterLocStart(), InitEnd);
2133e5dd7070Spatrick }
2134e5dd7070Spatrick return DeclaratorDecl::getSourceRange();
2135e5dd7070Spatrick }
2136e5dd7070Spatrick
2137e5dd7070Spatrick template<typename T>
getDeclLanguageLinkage(const T & D)2138e5dd7070Spatrick static LanguageLinkage getDeclLanguageLinkage(const T &D) {
2139e5dd7070Spatrick // C++ [dcl.link]p1: All function types, function names with external linkage,
2140e5dd7070Spatrick // and variable names with external linkage have a language linkage.
2141e5dd7070Spatrick if (!D.hasExternalFormalLinkage())
2142e5dd7070Spatrick return NoLanguageLinkage;
2143e5dd7070Spatrick
2144e5dd7070Spatrick // Language linkage is a C++ concept, but saying that everything else in C has
2145e5dd7070Spatrick // C language linkage fits the implementation nicely.
2146e5dd7070Spatrick ASTContext &Context = D.getASTContext();
2147e5dd7070Spatrick if (!Context.getLangOpts().CPlusPlus)
2148e5dd7070Spatrick return CLanguageLinkage;
2149e5dd7070Spatrick
2150e5dd7070Spatrick // C++ [dcl.link]p4: A C language linkage is ignored in determining the
2151e5dd7070Spatrick // language linkage of the names of class members and the function type of
2152e5dd7070Spatrick // class member functions.
2153e5dd7070Spatrick const DeclContext *DC = D.getDeclContext();
2154e5dd7070Spatrick if (DC->isRecord())
2155e5dd7070Spatrick return CXXLanguageLinkage;
2156e5dd7070Spatrick
2157e5dd7070Spatrick // If the first decl is in an extern "C" context, any other redeclaration
2158e5dd7070Spatrick // will have C language linkage. If the first one is not in an extern "C"
2159e5dd7070Spatrick // context, we would have reported an error for any other decl being in one.
2160e5dd7070Spatrick if (isFirstInExternCContext(&D))
2161e5dd7070Spatrick return CLanguageLinkage;
2162e5dd7070Spatrick return CXXLanguageLinkage;
2163e5dd7070Spatrick }
2164e5dd7070Spatrick
2165e5dd7070Spatrick template<typename T>
isDeclExternC(const T & D)2166e5dd7070Spatrick static bool isDeclExternC(const T &D) {
2167e5dd7070Spatrick // Since the context is ignored for class members, they can only have C++
2168e5dd7070Spatrick // language linkage or no language linkage.
2169e5dd7070Spatrick const DeclContext *DC = D.getDeclContext();
2170e5dd7070Spatrick if (DC->isRecord()) {
2171e5dd7070Spatrick assert(D.getASTContext().getLangOpts().CPlusPlus);
2172e5dd7070Spatrick return false;
2173e5dd7070Spatrick }
2174e5dd7070Spatrick
2175e5dd7070Spatrick return D.getLanguageLinkage() == CLanguageLinkage;
2176e5dd7070Spatrick }
2177e5dd7070Spatrick
getLanguageLinkage() const2178e5dd7070Spatrick LanguageLinkage VarDecl::getLanguageLinkage() const {
2179e5dd7070Spatrick return getDeclLanguageLinkage(*this);
2180e5dd7070Spatrick }
2181e5dd7070Spatrick
isExternC() const2182e5dd7070Spatrick bool VarDecl::isExternC() const {
2183e5dd7070Spatrick return isDeclExternC(*this);
2184e5dd7070Spatrick }
2185e5dd7070Spatrick
isInExternCContext() const2186e5dd7070Spatrick bool VarDecl::isInExternCContext() const {
2187e5dd7070Spatrick return getLexicalDeclContext()->isExternCContext();
2188e5dd7070Spatrick }
2189e5dd7070Spatrick
isInExternCXXContext() const2190e5dd7070Spatrick bool VarDecl::isInExternCXXContext() const {
2191e5dd7070Spatrick return getLexicalDeclContext()->isExternCXXContext();
2192e5dd7070Spatrick }
2193e5dd7070Spatrick
getCanonicalDecl()2194e5dd7070Spatrick VarDecl *VarDecl::getCanonicalDecl() { return getFirstDecl(); }
2195e5dd7070Spatrick
2196e5dd7070Spatrick VarDecl::DefinitionKind
isThisDeclarationADefinition(ASTContext & C) const2197e5dd7070Spatrick VarDecl::isThisDeclarationADefinition(ASTContext &C) const {
2198e5dd7070Spatrick if (isThisDeclarationADemotedDefinition())
2199e5dd7070Spatrick return DeclarationOnly;
2200e5dd7070Spatrick
2201e5dd7070Spatrick // C++ [basic.def]p2:
2202e5dd7070Spatrick // A declaration is a definition unless [...] it contains the 'extern'
2203e5dd7070Spatrick // specifier or a linkage-specification and neither an initializer [...],
2204e5dd7070Spatrick // it declares a non-inline static data member in a class declaration [...],
2205e5dd7070Spatrick // it declares a static data member outside a class definition and the variable
2206e5dd7070Spatrick // was defined within the class with the constexpr specifier [...],
2207e5dd7070Spatrick // C++1y [temp.expl.spec]p15:
2208e5dd7070Spatrick // An explicit specialization of a static data member or an explicit
2209e5dd7070Spatrick // specialization of a static data member template is a definition if the
2210e5dd7070Spatrick // declaration includes an initializer; otherwise, it is a declaration.
2211e5dd7070Spatrick //
2212e5dd7070Spatrick // FIXME: How do you declare (but not define) a partial specialization of
2213e5dd7070Spatrick // a static data member template outside the containing class?
2214e5dd7070Spatrick if (isStaticDataMember()) {
2215e5dd7070Spatrick if (isOutOfLine() &&
2216e5dd7070Spatrick !(getCanonicalDecl()->isInline() &&
2217e5dd7070Spatrick getCanonicalDecl()->isConstexpr()) &&
2218e5dd7070Spatrick (hasInit() ||
2219e5dd7070Spatrick // If the first declaration is out-of-line, this may be an
2220e5dd7070Spatrick // instantiation of an out-of-line partial specialization of a variable
2221e5dd7070Spatrick // template for which we have not yet instantiated the initializer.
2222e5dd7070Spatrick (getFirstDecl()->isOutOfLine()
2223e5dd7070Spatrick ? getTemplateSpecializationKind() == TSK_Undeclared
2224e5dd7070Spatrick : getTemplateSpecializationKind() !=
2225e5dd7070Spatrick TSK_ExplicitSpecialization) ||
2226e5dd7070Spatrick isa<VarTemplatePartialSpecializationDecl>(this)))
2227e5dd7070Spatrick return Definition;
2228a9ac8606Spatrick if (!isOutOfLine() && isInline())
2229e5dd7070Spatrick return Definition;
2230e5dd7070Spatrick return DeclarationOnly;
2231e5dd7070Spatrick }
2232e5dd7070Spatrick // C99 6.7p5:
2233e5dd7070Spatrick // A definition of an identifier is a declaration for that identifier that
2234e5dd7070Spatrick // [...] causes storage to be reserved for that object.
2235e5dd7070Spatrick // Note: that applies for all non-file-scope objects.
2236e5dd7070Spatrick // C99 6.9.2p1:
2237e5dd7070Spatrick // If the declaration of an identifier for an object has file scope and an
2238e5dd7070Spatrick // initializer, the declaration is an external definition for the identifier
2239e5dd7070Spatrick if (hasInit())
2240e5dd7070Spatrick return Definition;
2241e5dd7070Spatrick
2242e5dd7070Spatrick if (hasDefiningAttr())
2243e5dd7070Spatrick return Definition;
2244e5dd7070Spatrick
2245e5dd7070Spatrick if (const auto *SAA = getAttr<SelectAnyAttr>())
2246e5dd7070Spatrick if (!SAA->isInherited())
2247e5dd7070Spatrick return Definition;
2248e5dd7070Spatrick
2249e5dd7070Spatrick // A variable template specialization (other than a static data member
2250e5dd7070Spatrick // template or an explicit specialization) is a declaration until we
2251e5dd7070Spatrick // instantiate its initializer.
2252e5dd7070Spatrick if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(this)) {
2253e5dd7070Spatrick if (VTSD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization &&
2254e5dd7070Spatrick !isa<VarTemplatePartialSpecializationDecl>(VTSD) &&
2255e5dd7070Spatrick !VTSD->IsCompleteDefinition)
2256e5dd7070Spatrick return DeclarationOnly;
2257e5dd7070Spatrick }
2258e5dd7070Spatrick
2259e5dd7070Spatrick if (hasExternalStorage())
2260e5dd7070Spatrick return DeclarationOnly;
2261e5dd7070Spatrick
2262e5dd7070Spatrick // [dcl.link] p7:
2263e5dd7070Spatrick // A declaration directly contained in a linkage-specification is treated
2264e5dd7070Spatrick // as if it contains the extern specifier for the purpose of determining
2265e5dd7070Spatrick // the linkage of the declared name and whether it is a definition.
2266e5dd7070Spatrick if (isSingleLineLanguageLinkage(*this))
2267e5dd7070Spatrick return DeclarationOnly;
2268e5dd7070Spatrick
2269e5dd7070Spatrick // C99 6.9.2p2:
2270e5dd7070Spatrick // A declaration of an object that has file scope without an initializer,
2271e5dd7070Spatrick // and without a storage class specifier or the scs 'static', constitutes
2272e5dd7070Spatrick // a tentative definition.
2273e5dd7070Spatrick // No such thing in C++.
2274e5dd7070Spatrick if (!C.getLangOpts().CPlusPlus && isFileVarDecl())
2275e5dd7070Spatrick return TentativeDefinition;
2276e5dd7070Spatrick
2277e5dd7070Spatrick // What's left is (in C, block-scope) declarations without initializers or
2278e5dd7070Spatrick // external storage. These are definitions.
2279e5dd7070Spatrick return Definition;
2280e5dd7070Spatrick }
2281e5dd7070Spatrick
getActingDefinition()2282e5dd7070Spatrick VarDecl *VarDecl::getActingDefinition() {
2283e5dd7070Spatrick DefinitionKind Kind = isThisDeclarationADefinition();
2284e5dd7070Spatrick if (Kind != TentativeDefinition)
2285e5dd7070Spatrick return nullptr;
2286e5dd7070Spatrick
2287e5dd7070Spatrick VarDecl *LastTentative = nullptr;
2288*12c85518Srobert
2289*12c85518Srobert // Loop through the declaration chain, starting with the most recent.
2290*12c85518Srobert for (VarDecl *Decl = getMostRecentDecl(); Decl;
2291*12c85518Srobert Decl = Decl->getPreviousDecl()) {
2292*12c85518Srobert Kind = Decl->isThisDeclarationADefinition();
2293e5dd7070Spatrick if (Kind == Definition)
2294e5dd7070Spatrick return nullptr;
2295*12c85518Srobert // Record the first (most recent) TentativeDefinition that is encountered.
2296*12c85518Srobert if (Kind == TentativeDefinition && !LastTentative)
2297*12c85518Srobert LastTentative = Decl;
2298e5dd7070Spatrick }
2299*12c85518Srobert
2300e5dd7070Spatrick return LastTentative;
2301e5dd7070Spatrick }
2302e5dd7070Spatrick
getDefinition(ASTContext & C)2303e5dd7070Spatrick VarDecl *VarDecl::getDefinition(ASTContext &C) {
2304e5dd7070Spatrick VarDecl *First = getFirstDecl();
2305*12c85518Srobert for (auto *I : First->redecls()) {
2306e5dd7070Spatrick if (I->isThisDeclarationADefinition(C) == Definition)
2307e5dd7070Spatrick return I;
2308e5dd7070Spatrick }
2309e5dd7070Spatrick return nullptr;
2310e5dd7070Spatrick }
2311e5dd7070Spatrick
hasDefinition(ASTContext & C) const2312e5dd7070Spatrick VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const {
2313e5dd7070Spatrick DefinitionKind Kind = DeclarationOnly;
2314e5dd7070Spatrick
2315e5dd7070Spatrick const VarDecl *First = getFirstDecl();
2316*12c85518Srobert for (auto *I : First->redecls()) {
2317e5dd7070Spatrick Kind = std::max(Kind, I->isThisDeclarationADefinition(C));
2318e5dd7070Spatrick if (Kind == Definition)
2319e5dd7070Spatrick break;
2320e5dd7070Spatrick }
2321e5dd7070Spatrick
2322e5dd7070Spatrick return Kind;
2323e5dd7070Spatrick }
2324e5dd7070Spatrick
getAnyInitializer(const VarDecl * & D) const2325e5dd7070Spatrick const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const {
2326*12c85518Srobert for (auto *I : redecls()) {
2327e5dd7070Spatrick if (auto Expr = I->getInit()) {
2328e5dd7070Spatrick D = I;
2329e5dd7070Spatrick return Expr;
2330e5dd7070Spatrick }
2331e5dd7070Spatrick }
2332e5dd7070Spatrick return nullptr;
2333e5dd7070Spatrick }
2334e5dd7070Spatrick
hasInit() const2335e5dd7070Spatrick bool VarDecl::hasInit() const {
2336e5dd7070Spatrick if (auto *P = dyn_cast<ParmVarDecl>(this))
2337e5dd7070Spatrick if (P->hasUnparsedDefaultArg() || P->hasUninstantiatedDefaultArg())
2338e5dd7070Spatrick return false;
2339e5dd7070Spatrick
2340e5dd7070Spatrick return !Init.isNull();
2341e5dd7070Spatrick }
2342e5dd7070Spatrick
getInit()2343e5dd7070Spatrick Expr *VarDecl::getInit() {
2344e5dd7070Spatrick if (!hasInit())
2345e5dd7070Spatrick return nullptr;
2346e5dd7070Spatrick
2347e5dd7070Spatrick if (auto *S = Init.dyn_cast<Stmt *>())
2348e5dd7070Spatrick return cast<Expr>(S);
2349e5dd7070Spatrick
2350e5dd7070Spatrick return cast_or_null<Expr>(Init.get<EvaluatedStmt *>()->Value);
2351e5dd7070Spatrick }
2352e5dd7070Spatrick
getInitAddress()2353e5dd7070Spatrick Stmt **VarDecl::getInitAddress() {
2354e5dd7070Spatrick if (auto *ES = Init.dyn_cast<EvaluatedStmt *>())
2355e5dd7070Spatrick return &ES->Value;
2356e5dd7070Spatrick
2357e5dd7070Spatrick return Init.getAddrOfPtr1();
2358e5dd7070Spatrick }
2359e5dd7070Spatrick
getInitializingDeclaration()2360e5dd7070Spatrick VarDecl *VarDecl::getInitializingDeclaration() {
2361e5dd7070Spatrick VarDecl *Def = nullptr;
2362*12c85518Srobert for (auto *I : redecls()) {
2363e5dd7070Spatrick if (I->hasInit())
2364e5dd7070Spatrick return I;
2365e5dd7070Spatrick
2366e5dd7070Spatrick if (I->isThisDeclarationADefinition()) {
2367e5dd7070Spatrick if (isStaticDataMember())
2368e5dd7070Spatrick return I;
2369e5dd7070Spatrick Def = I;
2370e5dd7070Spatrick }
2371e5dd7070Spatrick }
2372e5dd7070Spatrick return Def;
2373e5dd7070Spatrick }
2374e5dd7070Spatrick
isOutOfLine() const2375e5dd7070Spatrick bool VarDecl::isOutOfLine() const {
2376e5dd7070Spatrick if (Decl::isOutOfLine())
2377e5dd7070Spatrick return true;
2378e5dd7070Spatrick
2379e5dd7070Spatrick if (!isStaticDataMember())
2380e5dd7070Spatrick return false;
2381e5dd7070Spatrick
2382e5dd7070Spatrick // If this static data member was instantiated from a static data member of
2383e5dd7070Spatrick // a class template, check whether that static data member was defined
2384e5dd7070Spatrick // out-of-line.
2385e5dd7070Spatrick if (VarDecl *VD = getInstantiatedFromStaticDataMember())
2386e5dd7070Spatrick return VD->isOutOfLine();
2387e5dd7070Spatrick
2388e5dd7070Spatrick return false;
2389e5dd7070Spatrick }
2390e5dd7070Spatrick
setInit(Expr * I)2391e5dd7070Spatrick void VarDecl::setInit(Expr *I) {
2392e5dd7070Spatrick if (auto *Eval = Init.dyn_cast<EvaluatedStmt *>()) {
2393e5dd7070Spatrick Eval->~EvaluatedStmt();
2394e5dd7070Spatrick getASTContext().Deallocate(Eval);
2395e5dd7070Spatrick }
2396e5dd7070Spatrick
2397e5dd7070Spatrick Init = I;
2398e5dd7070Spatrick }
2399e5dd7070Spatrick
mightBeUsableInConstantExpressions(const ASTContext & C) const2400a9ac8606Spatrick bool VarDecl::mightBeUsableInConstantExpressions(const ASTContext &C) const {
2401e5dd7070Spatrick const LangOptions &Lang = C.getLangOpts();
2402e5dd7070Spatrick
2403a9ac8606Spatrick // OpenCL permits const integral variables to be used in constant
2404a9ac8606Spatrick // expressions, like in C++98.
2405a9ac8606Spatrick if (!Lang.CPlusPlus && !Lang.OpenCL)
2406e5dd7070Spatrick return false;
2407e5dd7070Spatrick
2408e5dd7070Spatrick // Function parameters are never usable in constant expressions.
2409e5dd7070Spatrick if (isa<ParmVarDecl>(this))
2410e5dd7070Spatrick return false;
2411e5dd7070Spatrick
2412a9ac8606Spatrick // The values of weak variables are never usable in constant expressions.
2413a9ac8606Spatrick if (isWeak())
2414a9ac8606Spatrick return false;
2415a9ac8606Spatrick
2416e5dd7070Spatrick // In C++11, any variable of reference type can be used in a constant
2417e5dd7070Spatrick // expression if it is initialized by a constant expression.
2418e5dd7070Spatrick if (Lang.CPlusPlus11 && getType()->isReferenceType())
2419e5dd7070Spatrick return true;
2420e5dd7070Spatrick
2421e5dd7070Spatrick // Only const objects can be used in constant expressions in C++. C++98 does
2422e5dd7070Spatrick // not require the variable to be non-volatile, but we consider this to be a
2423e5dd7070Spatrick // defect.
2424a9ac8606Spatrick if (!getType().isConstant(C) || getType().isVolatileQualified())
2425e5dd7070Spatrick return false;
2426e5dd7070Spatrick
2427e5dd7070Spatrick // In C++, const, non-volatile variables of integral or enumeration types
2428e5dd7070Spatrick // can be used in constant expressions.
2429e5dd7070Spatrick if (getType()->isIntegralOrEnumerationType())
2430e5dd7070Spatrick return true;
2431e5dd7070Spatrick
2432e5dd7070Spatrick // Additionally, in C++11, non-volatile constexpr variables can be used in
2433e5dd7070Spatrick // constant expressions.
2434e5dd7070Spatrick return Lang.CPlusPlus11 && isConstexpr();
2435e5dd7070Spatrick }
2436e5dd7070Spatrick
isUsableInConstantExpressions(const ASTContext & Context) const2437a9ac8606Spatrick bool VarDecl::isUsableInConstantExpressions(const ASTContext &Context) const {
2438e5dd7070Spatrick // C++2a [expr.const]p3:
2439e5dd7070Spatrick // A variable is usable in constant expressions after its initializing
2440e5dd7070Spatrick // declaration is encountered...
2441e5dd7070Spatrick const VarDecl *DefVD = nullptr;
2442e5dd7070Spatrick const Expr *Init = getAnyInitializer(DefVD);
2443e5dd7070Spatrick if (!Init || Init->isValueDependent() || getType()->isDependentType())
2444e5dd7070Spatrick return false;
2445e5dd7070Spatrick // ... if it is a constexpr variable, or it is of reference type or of
2446e5dd7070Spatrick // const-qualified integral or enumeration type, ...
2447e5dd7070Spatrick if (!DefVD->mightBeUsableInConstantExpressions(Context))
2448e5dd7070Spatrick return false;
2449e5dd7070Spatrick // ... and its initializer is a constant initializer.
2450a9ac8606Spatrick if (Context.getLangOpts().CPlusPlus && !DefVD->hasConstantInitialization())
2451a9ac8606Spatrick return false;
2452a9ac8606Spatrick // C++98 [expr.const]p1:
2453a9ac8606Spatrick // An integral constant-expression can involve only [...] const variables
2454a9ac8606Spatrick // or static data members of integral or enumeration types initialized with
2455a9ac8606Spatrick // [integer] constant expressions (dcl.init)
2456a9ac8606Spatrick if ((Context.getLangOpts().CPlusPlus || Context.getLangOpts().OpenCL) &&
2457a9ac8606Spatrick !Context.getLangOpts().CPlusPlus11 && !DefVD->hasICEInitializer(Context))
2458a9ac8606Spatrick return false;
2459a9ac8606Spatrick return true;
2460e5dd7070Spatrick }
2461e5dd7070Spatrick
2462e5dd7070Spatrick /// Convert the initializer for this declaration to the elaborated EvaluatedStmt
2463e5dd7070Spatrick /// form, which contains extra information on the evaluated value of the
2464e5dd7070Spatrick /// initializer.
ensureEvaluatedStmt() const2465e5dd7070Spatrick EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const {
2466e5dd7070Spatrick auto *Eval = Init.dyn_cast<EvaluatedStmt *>();
2467e5dd7070Spatrick if (!Eval) {
2468e5dd7070Spatrick // Note: EvaluatedStmt contains an APValue, which usually holds
2469e5dd7070Spatrick // resources not allocated from the ASTContext. We need to do some
2470e5dd7070Spatrick // work to avoid leaking those, but we do so in VarDecl::evaluateValue
2471e5dd7070Spatrick // where we can detect whether there's anything to clean up or not.
2472e5dd7070Spatrick Eval = new (getASTContext()) EvaluatedStmt;
2473e5dd7070Spatrick Eval->Value = Init.get<Stmt *>();
2474e5dd7070Spatrick Init = Eval;
2475e5dd7070Spatrick }
2476e5dd7070Spatrick return Eval;
2477e5dd7070Spatrick }
2478e5dd7070Spatrick
getEvaluatedStmt() const2479a9ac8606Spatrick EvaluatedStmt *VarDecl::getEvaluatedStmt() const {
2480a9ac8606Spatrick return Init.dyn_cast<EvaluatedStmt *>();
2481e5dd7070Spatrick }
2482e5dd7070Spatrick
evaluateValue() const2483a9ac8606Spatrick APValue *VarDecl::evaluateValue() const {
2484a9ac8606Spatrick SmallVector<PartialDiagnosticAt, 8> Notes;
2485a9ac8606Spatrick return evaluateValueImpl(Notes, hasConstantInitialization());
2486a9ac8606Spatrick }
2487a9ac8606Spatrick
evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> & Notes,bool IsConstantInitialization) const2488a9ac8606Spatrick APValue *VarDecl::evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> &Notes,
2489a9ac8606Spatrick bool IsConstantInitialization) const {
2490e5dd7070Spatrick EvaluatedStmt *Eval = ensureEvaluatedStmt();
2491e5dd7070Spatrick
2492a9ac8606Spatrick const auto *Init = cast<Expr>(Eval->Value);
2493a9ac8606Spatrick assert(!Init->isValueDependent());
2494a9ac8606Spatrick
2495e5dd7070Spatrick // We only produce notes indicating why an initializer is non-constant the
2496e5dd7070Spatrick // first time it is evaluated. FIXME: The notes won't always be emitted the
2497e5dd7070Spatrick // first time we try evaluation, so might not be produced at all.
2498e5dd7070Spatrick if (Eval->WasEvaluated)
2499e5dd7070Spatrick return Eval->Evaluated.isAbsent() ? nullptr : &Eval->Evaluated;
2500e5dd7070Spatrick
2501e5dd7070Spatrick if (Eval->IsEvaluating) {
2502e5dd7070Spatrick // FIXME: Produce a diagnostic for self-initialization.
2503e5dd7070Spatrick return nullptr;
2504e5dd7070Spatrick }
2505e5dd7070Spatrick
2506e5dd7070Spatrick Eval->IsEvaluating = true;
2507e5dd7070Spatrick
2508a9ac8606Spatrick ASTContext &Ctx = getASTContext();
2509a9ac8606Spatrick bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, Ctx, this, Notes,
2510a9ac8606Spatrick IsConstantInitialization);
2511a9ac8606Spatrick
2512a9ac8606Spatrick // In C++11, this isn't a constant initializer if we produced notes. In that
2513a9ac8606Spatrick // case, we can't keep the result, because it may only be correct under the
2514a9ac8606Spatrick // assumption that the initializer is a constant context.
2515a9ac8606Spatrick if (IsConstantInitialization && Ctx.getLangOpts().CPlusPlus11 &&
2516a9ac8606Spatrick !Notes.empty())
2517a9ac8606Spatrick Result = false;
2518e5dd7070Spatrick
2519e5dd7070Spatrick // Ensure the computed APValue is cleaned up later if evaluation succeeded,
2520e5dd7070Spatrick // or that it's empty (so that there's nothing to clean up) if evaluation
2521e5dd7070Spatrick // failed.
2522e5dd7070Spatrick if (!Result)
2523e5dd7070Spatrick Eval->Evaluated = APValue();
2524e5dd7070Spatrick else if (Eval->Evaluated.needsCleanup())
2525a9ac8606Spatrick Ctx.addDestruction(&Eval->Evaluated);
2526e5dd7070Spatrick
2527e5dd7070Spatrick Eval->IsEvaluating = false;
2528e5dd7070Spatrick Eval->WasEvaluated = true;
2529e5dd7070Spatrick
2530e5dd7070Spatrick return Result ? &Eval->Evaluated : nullptr;
2531e5dd7070Spatrick }
2532e5dd7070Spatrick
getEvaluatedValue() const2533e5dd7070Spatrick APValue *VarDecl::getEvaluatedValue() const {
2534a9ac8606Spatrick if (EvaluatedStmt *Eval = getEvaluatedStmt())
2535e5dd7070Spatrick if (Eval->WasEvaluated)
2536e5dd7070Spatrick return &Eval->Evaluated;
2537e5dd7070Spatrick
2538e5dd7070Spatrick return nullptr;
2539e5dd7070Spatrick }
2540e5dd7070Spatrick
hasICEInitializer(const ASTContext & Context) const2541a9ac8606Spatrick bool VarDecl::hasICEInitializer(const ASTContext &Context) const {
2542a9ac8606Spatrick const Expr *Init = getInit();
2543a9ac8606Spatrick assert(Init && "no initializer");
2544e5dd7070Spatrick
2545e5dd7070Spatrick EvaluatedStmt *Eval = ensureEvaluatedStmt();
2546a9ac8606Spatrick if (!Eval->CheckedForICEInit) {
2547a9ac8606Spatrick Eval->CheckedForICEInit = true;
2548a9ac8606Spatrick Eval->HasICEInit = Init->isIntegerConstantExpr(Context);
2549a9ac8606Spatrick }
2550a9ac8606Spatrick return Eval->HasICEInit;
2551e5dd7070Spatrick }
2552e5dd7070Spatrick
hasConstantInitialization() const2553a9ac8606Spatrick bool VarDecl::hasConstantInitialization() const {
2554a9ac8606Spatrick // In C, all globals (and only globals) have constant initialization.
2555a9ac8606Spatrick if (hasGlobalStorage() && !getASTContext().getLangOpts().CPlusPlus)
2556a9ac8606Spatrick return true;
2557e5dd7070Spatrick
2558a9ac8606Spatrick // In C++, it depends on whether the evaluation at the point of definition
2559a9ac8606Spatrick // was evaluatable as a constant initializer.
2560a9ac8606Spatrick if (EvaluatedStmt *Eval = getEvaluatedStmt())
2561a9ac8606Spatrick return Eval->HasConstantInitialization;
2562a9ac8606Spatrick
2563e5dd7070Spatrick return false;
2564a9ac8606Spatrick }
2565e5dd7070Spatrick
checkForConstantInitialization(SmallVectorImpl<PartialDiagnosticAt> & Notes) const2566a9ac8606Spatrick bool VarDecl::checkForConstantInitialization(
2567a9ac8606Spatrick SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
2568a9ac8606Spatrick EvaluatedStmt *Eval = ensureEvaluatedStmt();
2569a9ac8606Spatrick // If we ask for the value before we know whether we have a constant
2570a9ac8606Spatrick // initializer, we can compute the wrong value (for example, due to
2571a9ac8606Spatrick // std::is_constant_evaluated()).
2572a9ac8606Spatrick assert(!Eval->WasEvaluated &&
2573a9ac8606Spatrick "already evaluated var value before checking for constant init");
2574a9ac8606Spatrick assert(getASTContext().getLangOpts().CPlusPlus && "only meaningful in C++");
2575a9ac8606Spatrick
2576a9ac8606Spatrick assert(!cast<Expr>(Eval->Value)->isValueDependent());
2577a9ac8606Spatrick
2578a9ac8606Spatrick // Evaluate the initializer to check whether it's a constant expression.
2579a9ac8606Spatrick Eval->HasConstantInitialization =
2580a9ac8606Spatrick evaluateValueImpl(Notes, true) && Notes.empty();
2581a9ac8606Spatrick
2582a9ac8606Spatrick // If evaluation as a constant initializer failed, allow re-evaluation as a
2583a9ac8606Spatrick // non-constant initializer if we later find we want the value.
2584a9ac8606Spatrick if (!Eval->HasConstantInitialization)
2585a9ac8606Spatrick Eval->WasEvaluated = false;
2586a9ac8606Spatrick
2587a9ac8606Spatrick return Eval->HasConstantInitialization;
2588e5dd7070Spatrick }
2589e5dd7070Spatrick
isParameterPack() const2590e5dd7070Spatrick bool VarDecl::isParameterPack() const {
2591e5dd7070Spatrick return isa<PackExpansionType>(getType());
2592e5dd7070Spatrick }
2593e5dd7070Spatrick
2594e5dd7070Spatrick template<typename DeclT>
getDefinitionOrSelf(DeclT * D)2595e5dd7070Spatrick static DeclT *getDefinitionOrSelf(DeclT *D) {
2596e5dd7070Spatrick assert(D);
2597e5dd7070Spatrick if (auto *Def = D->getDefinition())
2598e5dd7070Spatrick return Def;
2599e5dd7070Spatrick return D;
2600e5dd7070Spatrick }
2601e5dd7070Spatrick
isEscapingByref() const2602e5dd7070Spatrick bool VarDecl::isEscapingByref() const {
2603e5dd7070Spatrick return hasAttr<BlocksAttr>() && NonParmVarDeclBits.EscapingByref;
2604e5dd7070Spatrick }
2605e5dd7070Spatrick
isNonEscapingByref() const2606e5dd7070Spatrick bool VarDecl::isNonEscapingByref() const {
2607e5dd7070Spatrick return hasAttr<BlocksAttr>() && !NonParmVarDeclBits.EscapingByref;
2608e5dd7070Spatrick }
2609e5dd7070Spatrick
hasDependentAlignment() const2610a9ac8606Spatrick bool VarDecl::hasDependentAlignment() const {
2611a9ac8606Spatrick QualType T = getType();
2612*12c85518Srobert return T->isDependentType() || T->isUndeducedType() ||
2613a9ac8606Spatrick llvm::any_of(specific_attrs<AlignedAttr>(), [](const AlignedAttr *AA) {
2614a9ac8606Spatrick return AA->isAlignmentDependent();
2615a9ac8606Spatrick });
2616a9ac8606Spatrick }
2617a9ac8606Spatrick
getTemplateInstantiationPattern() const2618e5dd7070Spatrick VarDecl *VarDecl::getTemplateInstantiationPattern() const {
2619e5dd7070Spatrick const VarDecl *VD = this;
2620e5dd7070Spatrick
2621e5dd7070Spatrick // If this is an instantiated member, walk back to the template from which
2622e5dd7070Spatrick // it was instantiated.
2623e5dd7070Spatrick if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo()) {
2624e5dd7070Spatrick if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) {
2625e5dd7070Spatrick VD = VD->getInstantiatedFromStaticDataMember();
2626e5dd7070Spatrick while (auto *NewVD = VD->getInstantiatedFromStaticDataMember())
2627e5dd7070Spatrick VD = NewVD;
2628e5dd7070Spatrick }
2629e5dd7070Spatrick }
2630e5dd7070Spatrick
2631e5dd7070Spatrick // If it's an instantiated variable template specialization, find the
2632e5dd7070Spatrick // template or partial specialization from which it was instantiated.
2633e5dd7070Spatrick if (auto *VDTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(VD)) {
2634e5dd7070Spatrick if (isTemplateInstantiation(VDTemplSpec->getTemplateSpecializationKind())) {
2635e5dd7070Spatrick auto From = VDTemplSpec->getInstantiatedFrom();
2636e5dd7070Spatrick if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) {
2637e5dd7070Spatrick while (!VTD->isMemberSpecialization()) {
2638e5dd7070Spatrick auto *NewVTD = VTD->getInstantiatedFromMemberTemplate();
2639e5dd7070Spatrick if (!NewVTD)
2640e5dd7070Spatrick break;
2641e5dd7070Spatrick VTD = NewVTD;
2642e5dd7070Spatrick }
2643e5dd7070Spatrick return getDefinitionOrSelf(VTD->getTemplatedDecl());
2644e5dd7070Spatrick }
2645e5dd7070Spatrick if (auto *VTPSD =
2646e5dd7070Spatrick From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
2647e5dd7070Spatrick while (!VTPSD->isMemberSpecialization()) {
2648e5dd7070Spatrick auto *NewVTPSD = VTPSD->getInstantiatedFromMember();
2649e5dd7070Spatrick if (!NewVTPSD)
2650e5dd7070Spatrick break;
2651e5dd7070Spatrick VTPSD = NewVTPSD;
2652e5dd7070Spatrick }
2653e5dd7070Spatrick return getDefinitionOrSelf<VarDecl>(VTPSD);
2654e5dd7070Spatrick }
2655e5dd7070Spatrick }
2656e5dd7070Spatrick }
2657e5dd7070Spatrick
2658e5dd7070Spatrick // If this is the pattern of a variable template, find where it was
2659e5dd7070Spatrick // instantiated from. FIXME: Is this necessary?
2660e5dd7070Spatrick if (VarTemplateDecl *VarTemplate = VD->getDescribedVarTemplate()) {
2661e5dd7070Spatrick while (!VarTemplate->isMemberSpecialization()) {
2662e5dd7070Spatrick auto *NewVT = VarTemplate->getInstantiatedFromMemberTemplate();
2663e5dd7070Spatrick if (!NewVT)
2664e5dd7070Spatrick break;
2665e5dd7070Spatrick VarTemplate = NewVT;
2666e5dd7070Spatrick }
2667e5dd7070Spatrick
2668e5dd7070Spatrick return getDefinitionOrSelf(VarTemplate->getTemplatedDecl());
2669e5dd7070Spatrick }
2670e5dd7070Spatrick
2671e5dd7070Spatrick if (VD == this)
2672e5dd7070Spatrick return nullptr;
2673e5dd7070Spatrick return getDefinitionOrSelf(const_cast<VarDecl*>(VD));
2674e5dd7070Spatrick }
2675e5dd7070Spatrick
getInstantiatedFromStaticDataMember() const2676e5dd7070Spatrick VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
2677e5dd7070Spatrick if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
2678e5dd7070Spatrick return cast<VarDecl>(MSI->getInstantiatedFrom());
2679e5dd7070Spatrick
2680e5dd7070Spatrick return nullptr;
2681e5dd7070Spatrick }
2682e5dd7070Spatrick
getTemplateSpecializationKind() const2683e5dd7070Spatrick TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const {
2684e5dd7070Spatrick if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this))
2685e5dd7070Spatrick return Spec->getSpecializationKind();
2686e5dd7070Spatrick
2687e5dd7070Spatrick if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
2688e5dd7070Spatrick return MSI->getTemplateSpecializationKind();
2689e5dd7070Spatrick
2690e5dd7070Spatrick return TSK_Undeclared;
2691e5dd7070Spatrick }
2692e5dd7070Spatrick
2693e5dd7070Spatrick TemplateSpecializationKind
getTemplateSpecializationKindForInstantiation() const2694e5dd7070Spatrick VarDecl::getTemplateSpecializationKindForInstantiation() const {
2695e5dd7070Spatrick if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
2696e5dd7070Spatrick return MSI->getTemplateSpecializationKind();
2697e5dd7070Spatrick
2698e5dd7070Spatrick if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this))
2699e5dd7070Spatrick return Spec->getSpecializationKind();
2700e5dd7070Spatrick
2701e5dd7070Spatrick return TSK_Undeclared;
2702e5dd7070Spatrick }
2703e5dd7070Spatrick
getPointOfInstantiation() const2704e5dd7070Spatrick SourceLocation VarDecl::getPointOfInstantiation() const {
2705e5dd7070Spatrick if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this))
2706e5dd7070Spatrick return Spec->getPointOfInstantiation();
2707e5dd7070Spatrick
2708e5dd7070Spatrick if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
2709e5dd7070Spatrick return MSI->getPointOfInstantiation();
2710e5dd7070Spatrick
2711e5dd7070Spatrick return SourceLocation();
2712e5dd7070Spatrick }
2713e5dd7070Spatrick
getDescribedVarTemplate() const2714e5dd7070Spatrick VarTemplateDecl *VarDecl::getDescribedVarTemplate() const {
2715e5dd7070Spatrick return getASTContext().getTemplateOrSpecializationInfo(this)
2716e5dd7070Spatrick .dyn_cast<VarTemplateDecl *>();
2717e5dd7070Spatrick }
2718e5dd7070Spatrick
setDescribedVarTemplate(VarTemplateDecl * Template)2719e5dd7070Spatrick void VarDecl::setDescribedVarTemplate(VarTemplateDecl *Template) {
2720e5dd7070Spatrick getASTContext().setTemplateOrSpecializationInfo(this, Template);
2721e5dd7070Spatrick }
2722e5dd7070Spatrick
isKnownToBeDefined() const2723e5dd7070Spatrick bool VarDecl::isKnownToBeDefined() const {
2724e5dd7070Spatrick const auto &LangOpts = getASTContext().getLangOpts();
2725e5dd7070Spatrick // In CUDA mode without relocatable device code, variables of form 'extern
2726e5dd7070Spatrick // __shared__ Foo foo[]' are pointers to the base of the GPU core's shared
2727e5dd7070Spatrick // memory pool. These are never undefined variables, even if they appear
2728e5dd7070Spatrick // inside of an anon namespace or static function.
2729e5dd7070Spatrick //
2730e5dd7070Spatrick // With CUDA relocatable device code enabled, these variables don't get
2731e5dd7070Spatrick // special handling; they're treated like regular extern variables.
2732e5dd7070Spatrick if (LangOpts.CUDA && !LangOpts.GPURelocatableDeviceCode &&
2733e5dd7070Spatrick hasExternalStorage() && hasAttr<CUDASharedAttr>() &&
2734e5dd7070Spatrick isa<IncompleteArrayType>(getType()))
2735e5dd7070Spatrick return true;
2736e5dd7070Spatrick
2737e5dd7070Spatrick return hasDefinition();
2738e5dd7070Spatrick }
2739e5dd7070Spatrick
isNoDestroy(const ASTContext & Ctx) const2740e5dd7070Spatrick bool VarDecl::isNoDestroy(const ASTContext &Ctx) const {
2741e5dd7070Spatrick return hasGlobalStorage() && (hasAttr<NoDestroyAttr>() ||
2742e5dd7070Spatrick (!Ctx.getLangOpts().RegisterStaticDestructors &&
2743e5dd7070Spatrick !hasAttr<AlwaysDestroyAttr>()));
2744e5dd7070Spatrick }
2745e5dd7070Spatrick
2746e5dd7070Spatrick QualType::DestructionKind
needsDestruction(const ASTContext & Ctx) const2747e5dd7070Spatrick VarDecl::needsDestruction(const ASTContext &Ctx) const {
2748a9ac8606Spatrick if (EvaluatedStmt *Eval = getEvaluatedStmt())
2749e5dd7070Spatrick if (Eval->HasConstantDestruction)
2750e5dd7070Spatrick return QualType::DK_none;
2751e5dd7070Spatrick
2752e5dd7070Spatrick if (isNoDestroy(Ctx))
2753e5dd7070Spatrick return QualType::DK_none;
2754e5dd7070Spatrick
2755e5dd7070Spatrick return getType().isDestructedType();
2756e5dd7070Spatrick }
2757e5dd7070Spatrick
hasFlexibleArrayInit(const ASTContext & Ctx) const2758*12c85518Srobert bool VarDecl::hasFlexibleArrayInit(const ASTContext &Ctx) const {
2759*12c85518Srobert assert(hasInit() && "Expect initializer to check for flexible array init");
2760*12c85518Srobert auto *Ty = getType()->getAs<RecordType>();
2761*12c85518Srobert if (!Ty || !Ty->getDecl()->hasFlexibleArrayMember())
2762*12c85518Srobert return false;
2763*12c85518Srobert auto *List = dyn_cast<InitListExpr>(getInit()->IgnoreParens());
2764*12c85518Srobert if (!List)
2765*12c85518Srobert return false;
2766*12c85518Srobert const Expr *FlexibleInit = List->getInit(List->getNumInits() - 1);
2767*12c85518Srobert auto InitTy = Ctx.getAsConstantArrayType(FlexibleInit->getType());
2768*12c85518Srobert if (!InitTy)
2769*12c85518Srobert return false;
2770*12c85518Srobert return InitTy->getSize() != 0;
2771*12c85518Srobert }
2772*12c85518Srobert
getFlexibleArrayInitChars(const ASTContext & Ctx) const2773*12c85518Srobert CharUnits VarDecl::getFlexibleArrayInitChars(const ASTContext &Ctx) const {
2774*12c85518Srobert assert(hasInit() && "Expect initializer to check for flexible array init");
2775*12c85518Srobert auto *Ty = getType()->getAs<RecordType>();
2776*12c85518Srobert if (!Ty || !Ty->getDecl()->hasFlexibleArrayMember())
2777*12c85518Srobert return CharUnits::Zero();
2778*12c85518Srobert auto *List = dyn_cast<InitListExpr>(getInit()->IgnoreParens());
2779*12c85518Srobert if (!List)
2780*12c85518Srobert return CharUnits::Zero();
2781*12c85518Srobert const Expr *FlexibleInit = List->getInit(List->getNumInits() - 1);
2782*12c85518Srobert auto InitTy = Ctx.getAsConstantArrayType(FlexibleInit->getType());
2783*12c85518Srobert if (!InitTy)
2784*12c85518Srobert return CharUnits::Zero();
2785*12c85518Srobert CharUnits FlexibleArraySize = Ctx.getTypeSizeInChars(InitTy);
2786*12c85518Srobert const ASTRecordLayout &RL = Ctx.getASTRecordLayout(Ty->getDecl());
2787*12c85518Srobert CharUnits FlexibleArrayOffset =
2788*12c85518Srobert Ctx.toCharUnitsFromBits(RL.getFieldOffset(RL.getFieldCount() - 1));
2789*12c85518Srobert if (FlexibleArrayOffset + FlexibleArraySize < RL.getSize())
2790*12c85518Srobert return CharUnits::Zero();
2791*12c85518Srobert return FlexibleArrayOffset + FlexibleArraySize - RL.getSize();
2792*12c85518Srobert }
2793*12c85518Srobert
getMemberSpecializationInfo() const2794e5dd7070Spatrick MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const {
2795e5dd7070Spatrick if (isStaticDataMember())
2796e5dd7070Spatrick // FIXME: Remove ?
2797e5dd7070Spatrick // return getASTContext().getInstantiatedFromStaticDataMember(this);
2798e5dd7070Spatrick return getASTContext().getTemplateOrSpecializationInfo(this)
2799e5dd7070Spatrick .dyn_cast<MemberSpecializationInfo *>();
2800e5dd7070Spatrick return nullptr;
2801e5dd7070Spatrick }
2802e5dd7070Spatrick
setTemplateSpecializationKind(TemplateSpecializationKind TSK,SourceLocation PointOfInstantiation)2803e5dd7070Spatrick void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
2804e5dd7070Spatrick SourceLocation PointOfInstantiation) {
2805e5dd7070Spatrick assert((isa<VarTemplateSpecializationDecl>(this) ||
2806e5dd7070Spatrick getMemberSpecializationInfo()) &&
2807e5dd7070Spatrick "not a variable or static data member template specialization");
2808e5dd7070Spatrick
2809e5dd7070Spatrick if (VarTemplateSpecializationDecl *Spec =
2810e5dd7070Spatrick dyn_cast<VarTemplateSpecializationDecl>(this)) {
2811e5dd7070Spatrick Spec->setSpecializationKind(TSK);
2812e5dd7070Spatrick if (TSK != TSK_ExplicitSpecialization &&
2813e5dd7070Spatrick PointOfInstantiation.isValid() &&
2814e5dd7070Spatrick Spec->getPointOfInstantiation().isInvalid()) {
2815e5dd7070Spatrick Spec->setPointOfInstantiation(PointOfInstantiation);
2816e5dd7070Spatrick if (ASTMutationListener *L = getASTContext().getASTMutationListener())
2817e5dd7070Spatrick L->InstantiationRequested(this);
2818e5dd7070Spatrick }
2819e5dd7070Spatrick } else if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) {
2820e5dd7070Spatrick MSI->setTemplateSpecializationKind(TSK);
2821e5dd7070Spatrick if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() &&
2822e5dd7070Spatrick MSI->getPointOfInstantiation().isInvalid()) {
2823e5dd7070Spatrick MSI->setPointOfInstantiation(PointOfInstantiation);
2824e5dd7070Spatrick if (ASTMutationListener *L = getASTContext().getASTMutationListener())
2825e5dd7070Spatrick L->InstantiationRequested(this);
2826e5dd7070Spatrick }
2827e5dd7070Spatrick }
2828e5dd7070Spatrick }
2829e5dd7070Spatrick
2830e5dd7070Spatrick void
setInstantiationOfStaticDataMember(VarDecl * VD,TemplateSpecializationKind TSK)2831e5dd7070Spatrick VarDecl::setInstantiationOfStaticDataMember(VarDecl *VD,
2832e5dd7070Spatrick TemplateSpecializationKind TSK) {
2833e5dd7070Spatrick assert(getASTContext().getTemplateOrSpecializationInfo(this).isNull() &&
2834e5dd7070Spatrick "Previous template or instantiation?");
2835e5dd7070Spatrick getASTContext().setInstantiatedFromStaticDataMember(this, VD, TSK);
2836e5dd7070Spatrick }
2837e5dd7070Spatrick
2838e5dd7070Spatrick //===----------------------------------------------------------------------===//
2839e5dd7070Spatrick // ParmVarDecl Implementation
2840e5dd7070Spatrick //===----------------------------------------------------------------------===//
2841e5dd7070Spatrick
Create(ASTContext & C,DeclContext * DC,SourceLocation StartLoc,SourceLocation IdLoc,IdentifierInfo * Id,QualType T,TypeSourceInfo * TInfo,StorageClass S,Expr * DefArg)2842e5dd7070Spatrick ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
2843e5dd7070Spatrick SourceLocation StartLoc,
2844e5dd7070Spatrick SourceLocation IdLoc, IdentifierInfo *Id,
2845e5dd7070Spatrick QualType T, TypeSourceInfo *TInfo,
2846e5dd7070Spatrick StorageClass S, Expr *DefArg) {
2847e5dd7070Spatrick return new (C, DC) ParmVarDecl(ParmVar, C, DC, StartLoc, IdLoc, Id, T, TInfo,
2848e5dd7070Spatrick S, DefArg);
2849e5dd7070Spatrick }
2850e5dd7070Spatrick
getOriginalType() const2851e5dd7070Spatrick QualType ParmVarDecl::getOriginalType() const {
2852e5dd7070Spatrick TypeSourceInfo *TSI = getTypeSourceInfo();
2853e5dd7070Spatrick QualType T = TSI ? TSI->getType() : getType();
2854e5dd7070Spatrick if (const auto *DT = dyn_cast<DecayedType>(T))
2855e5dd7070Spatrick return DT->getOriginalType();
2856e5dd7070Spatrick return T;
2857e5dd7070Spatrick }
2858e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID)2859e5dd7070Spatrick ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
2860e5dd7070Spatrick return new (C, ID)
2861e5dd7070Spatrick ParmVarDecl(ParmVar, C, nullptr, SourceLocation(), SourceLocation(),
2862e5dd7070Spatrick nullptr, QualType(), nullptr, SC_None, nullptr);
2863e5dd7070Spatrick }
2864e5dd7070Spatrick
getSourceRange() const2865e5dd7070Spatrick SourceRange ParmVarDecl::getSourceRange() const {
2866e5dd7070Spatrick if (!hasInheritedDefaultArg()) {
2867e5dd7070Spatrick SourceRange ArgRange = getDefaultArgRange();
2868e5dd7070Spatrick if (ArgRange.isValid())
2869e5dd7070Spatrick return SourceRange(getOuterLocStart(), ArgRange.getEnd());
2870e5dd7070Spatrick }
2871e5dd7070Spatrick
2872e5dd7070Spatrick // DeclaratorDecl considers the range of postfix types as overlapping with the
2873e5dd7070Spatrick // declaration name, but this is not the case with parameters in ObjC methods.
2874e5dd7070Spatrick if (isa<ObjCMethodDecl>(getDeclContext()))
2875e5dd7070Spatrick return SourceRange(DeclaratorDecl::getBeginLoc(), getLocation());
2876e5dd7070Spatrick
2877e5dd7070Spatrick return DeclaratorDecl::getSourceRange();
2878e5dd7070Spatrick }
2879e5dd7070Spatrick
isDestroyedInCallee() const2880a9ac8606Spatrick bool ParmVarDecl::isDestroyedInCallee() const {
2881*12c85518Srobert // ns_consumed only affects code generation in ARC
2882a9ac8606Spatrick if (hasAttr<NSConsumedAttr>())
2883*12c85518Srobert return getASTContext().getLangOpts().ObjCAutoRefCount;
2884a9ac8606Spatrick
2885*12c85518Srobert // FIXME: isParamDestroyedInCallee() should probably imply
2886*12c85518Srobert // isDestructedType()
2887a9ac8606Spatrick auto *RT = getType()->getAs<RecordType>();
2888*12c85518Srobert if (RT && RT->getDecl()->isParamDestroyedInCallee() &&
2889*12c85518Srobert getType().isDestructedType())
2890a9ac8606Spatrick return true;
2891a9ac8606Spatrick
2892a9ac8606Spatrick return false;
2893a9ac8606Spatrick }
2894a9ac8606Spatrick
getDefaultArg()2895e5dd7070Spatrick Expr *ParmVarDecl::getDefaultArg() {
2896e5dd7070Spatrick assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!");
2897e5dd7070Spatrick assert(!hasUninstantiatedDefaultArg() &&
2898e5dd7070Spatrick "Default argument is not yet instantiated!");
2899e5dd7070Spatrick
2900e5dd7070Spatrick Expr *Arg = getInit();
2901e5dd7070Spatrick if (auto *E = dyn_cast_or_null<FullExpr>(Arg))
2902e5dd7070Spatrick return E->getSubExpr();
2903e5dd7070Spatrick
2904e5dd7070Spatrick return Arg;
2905e5dd7070Spatrick }
2906e5dd7070Spatrick
setDefaultArg(Expr * defarg)2907e5dd7070Spatrick void ParmVarDecl::setDefaultArg(Expr *defarg) {
2908e5dd7070Spatrick ParmVarDeclBits.DefaultArgKind = DAK_Normal;
2909e5dd7070Spatrick Init = defarg;
2910e5dd7070Spatrick }
2911e5dd7070Spatrick
getDefaultArgRange() const2912e5dd7070Spatrick SourceRange ParmVarDecl::getDefaultArgRange() const {
2913e5dd7070Spatrick switch (ParmVarDeclBits.DefaultArgKind) {
2914e5dd7070Spatrick case DAK_None:
2915e5dd7070Spatrick case DAK_Unparsed:
2916e5dd7070Spatrick // Nothing we can do here.
2917e5dd7070Spatrick return SourceRange();
2918e5dd7070Spatrick
2919e5dd7070Spatrick case DAK_Uninstantiated:
2920e5dd7070Spatrick return getUninstantiatedDefaultArg()->getSourceRange();
2921e5dd7070Spatrick
2922e5dd7070Spatrick case DAK_Normal:
2923e5dd7070Spatrick if (const Expr *E = getInit())
2924e5dd7070Spatrick return E->getSourceRange();
2925e5dd7070Spatrick
2926e5dd7070Spatrick // Missing an actual expression, may be invalid.
2927e5dd7070Spatrick return SourceRange();
2928e5dd7070Spatrick }
2929e5dd7070Spatrick llvm_unreachable("Invalid default argument kind.");
2930e5dd7070Spatrick }
2931e5dd7070Spatrick
setUninstantiatedDefaultArg(Expr * arg)2932e5dd7070Spatrick void ParmVarDecl::setUninstantiatedDefaultArg(Expr *arg) {
2933e5dd7070Spatrick ParmVarDeclBits.DefaultArgKind = DAK_Uninstantiated;
2934e5dd7070Spatrick Init = arg;
2935e5dd7070Spatrick }
2936e5dd7070Spatrick
getUninstantiatedDefaultArg()2937e5dd7070Spatrick Expr *ParmVarDecl::getUninstantiatedDefaultArg() {
2938e5dd7070Spatrick assert(hasUninstantiatedDefaultArg() &&
2939e5dd7070Spatrick "Wrong kind of initialization expression!");
2940e5dd7070Spatrick return cast_or_null<Expr>(Init.get<Stmt *>());
2941e5dd7070Spatrick }
2942e5dd7070Spatrick
hasDefaultArg() const2943e5dd7070Spatrick bool ParmVarDecl::hasDefaultArg() const {
2944e5dd7070Spatrick // FIXME: We should just return false for DAK_None here once callers are
2945e5dd7070Spatrick // prepared for the case that we encountered an invalid default argument and
2946e5dd7070Spatrick // were unable to even build an invalid expression.
2947e5dd7070Spatrick return hasUnparsedDefaultArg() || hasUninstantiatedDefaultArg() ||
2948e5dd7070Spatrick !Init.isNull();
2949e5dd7070Spatrick }
2950e5dd7070Spatrick
setParameterIndexLarge(unsigned parameterIndex)2951e5dd7070Spatrick void ParmVarDecl::setParameterIndexLarge(unsigned parameterIndex) {
2952e5dd7070Spatrick getASTContext().setParameterIndex(this, parameterIndex);
2953e5dd7070Spatrick ParmVarDeclBits.ParameterIndex = ParameterIndexSentinel;
2954e5dd7070Spatrick }
2955e5dd7070Spatrick
getParameterIndexLarge() const2956e5dd7070Spatrick unsigned ParmVarDecl::getParameterIndexLarge() const {
2957e5dd7070Spatrick return getASTContext().getParameterIndex(this);
2958e5dd7070Spatrick }
2959e5dd7070Spatrick
2960e5dd7070Spatrick //===----------------------------------------------------------------------===//
2961e5dd7070Spatrick // FunctionDecl Implementation
2962e5dd7070Spatrick //===----------------------------------------------------------------------===//
2963e5dd7070Spatrick
FunctionDecl(Kind DK,ASTContext & C,DeclContext * DC,SourceLocation StartLoc,const DeclarationNameInfo & NameInfo,QualType T,TypeSourceInfo * TInfo,StorageClass S,bool UsesFPIntrin,bool isInlineSpecified,ConstexprSpecKind ConstexprKind,Expr * TrailingRequiresClause)2964e5dd7070Spatrick FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
2965e5dd7070Spatrick SourceLocation StartLoc,
2966e5dd7070Spatrick const DeclarationNameInfo &NameInfo, QualType T,
2967e5dd7070Spatrick TypeSourceInfo *TInfo, StorageClass S,
2968*12c85518Srobert bool UsesFPIntrin, bool isInlineSpecified,
2969e5dd7070Spatrick ConstexprSpecKind ConstexprKind,
2970e5dd7070Spatrick Expr *TrailingRequiresClause)
2971e5dd7070Spatrick : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
2972e5dd7070Spatrick StartLoc),
2973e5dd7070Spatrick DeclContext(DK), redeclarable_base(C), Body(), ODRHash(0),
2974e5dd7070Spatrick EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) {
2975e5dd7070Spatrick assert(T.isNull() || T->isFunctionType());
2976e5dd7070Spatrick FunctionDeclBits.SClass = S;
2977e5dd7070Spatrick FunctionDeclBits.IsInline = isInlineSpecified;
2978e5dd7070Spatrick FunctionDeclBits.IsInlineSpecified = isInlineSpecified;
2979e5dd7070Spatrick FunctionDeclBits.IsVirtualAsWritten = false;
2980e5dd7070Spatrick FunctionDeclBits.IsPure = false;
2981e5dd7070Spatrick FunctionDeclBits.HasInheritedPrototype = false;
2982e5dd7070Spatrick FunctionDeclBits.HasWrittenPrototype = true;
2983e5dd7070Spatrick FunctionDeclBits.IsDeleted = false;
2984e5dd7070Spatrick FunctionDeclBits.IsTrivial = false;
2985e5dd7070Spatrick FunctionDeclBits.IsTrivialForCall = false;
2986e5dd7070Spatrick FunctionDeclBits.IsDefaulted = false;
2987e5dd7070Spatrick FunctionDeclBits.IsExplicitlyDefaulted = false;
2988e5dd7070Spatrick FunctionDeclBits.HasDefaultedFunctionInfo = false;
2989*12c85518Srobert FunctionDeclBits.IsIneligibleOrNotSelected = false;
2990e5dd7070Spatrick FunctionDeclBits.HasImplicitReturnZero = false;
2991e5dd7070Spatrick FunctionDeclBits.IsLateTemplateParsed = false;
2992a9ac8606Spatrick FunctionDeclBits.ConstexprKind = static_cast<uint64_t>(ConstexprKind);
2993e5dd7070Spatrick FunctionDeclBits.InstantiationIsPending = false;
2994e5dd7070Spatrick FunctionDeclBits.UsesSEHTry = false;
2995*12c85518Srobert FunctionDeclBits.UsesFPIntrin = UsesFPIntrin;
2996e5dd7070Spatrick FunctionDeclBits.HasSkippedBody = false;
2997e5dd7070Spatrick FunctionDeclBits.WillHaveBody = false;
2998e5dd7070Spatrick FunctionDeclBits.IsMultiVersion = false;
2999e5dd7070Spatrick FunctionDeclBits.IsCopyDeductionCandidate = false;
3000e5dd7070Spatrick FunctionDeclBits.HasODRHash = false;
3001*12c85518Srobert FunctionDeclBits.FriendConstraintRefersToEnclosingTemplate = false;
3002e5dd7070Spatrick if (TrailingRequiresClause)
3003e5dd7070Spatrick setTrailingRequiresClause(TrailingRequiresClause);
3004e5dd7070Spatrick }
3005e5dd7070Spatrick
getNameForDiagnostic(raw_ostream & OS,const PrintingPolicy & Policy,bool Qualified) const3006e5dd7070Spatrick void FunctionDecl::getNameForDiagnostic(
3007e5dd7070Spatrick raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
3008e5dd7070Spatrick NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
3009e5dd7070Spatrick const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs();
3010e5dd7070Spatrick if (TemplateArgs)
3011e5dd7070Spatrick printTemplateArgumentList(OS, TemplateArgs->asArray(), Policy);
3012e5dd7070Spatrick }
3013e5dd7070Spatrick
isVariadic() const3014e5dd7070Spatrick bool FunctionDecl::isVariadic() const {
3015e5dd7070Spatrick if (const auto *FT = getType()->getAs<FunctionProtoType>())
3016e5dd7070Spatrick return FT->isVariadic();
3017e5dd7070Spatrick return false;
3018e5dd7070Spatrick }
3019e5dd7070Spatrick
3020e5dd7070Spatrick FunctionDecl::DefaultedFunctionInfo *
Create(ASTContext & Context,ArrayRef<DeclAccessPair> Lookups)3021e5dd7070Spatrick FunctionDecl::DefaultedFunctionInfo::Create(ASTContext &Context,
3022e5dd7070Spatrick ArrayRef<DeclAccessPair> Lookups) {
3023e5dd7070Spatrick DefaultedFunctionInfo *Info = new (Context.Allocate(
3024e5dd7070Spatrick totalSizeToAlloc<DeclAccessPair>(Lookups.size()),
3025e5dd7070Spatrick std::max(alignof(DefaultedFunctionInfo), alignof(DeclAccessPair))))
3026e5dd7070Spatrick DefaultedFunctionInfo;
3027e5dd7070Spatrick Info->NumLookups = Lookups.size();
3028e5dd7070Spatrick std::uninitialized_copy(Lookups.begin(), Lookups.end(),
3029e5dd7070Spatrick Info->getTrailingObjects<DeclAccessPair>());
3030e5dd7070Spatrick return Info;
3031e5dd7070Spatrick }
3032e5dd7070Spatrick
setDefaultedFunctionInfo(DefaultedFunctionInfo * Info)3033e5dd7070Spatrick void FunctionDecl::setDefaultedFunctionInfo(DefaultedFunctionInfo *Info) {
3034e5dd7070Spatrick assert(!FunctionDeclBits.HasDefaultedFunctionInfo && "already have this");
3035e5dd7070Spatrick assert(!Body && "can't replace function body with defaulted function info");
3036e5dd7070Spatrick
3037e5dd7070Spatrick FunctionDeclBits.HasDefaultedFunctionInfo = true;
3038e5dd7070Spatrick DefaultedInfo = Info;
3039e5dd7070Spatrick }
3040e5dd7070Spatrick
3041e5dd7070Spatrick FunctionDecl::DefaultedFunctionInfo *
getDefaultedFunctionInfo() const3042e5dd7070Spatrick FunctionDecl::getDefaultedFunctionInfo() const {
3043e5dd7070Spatrick return FunctionDeclBits.HasDefaultedFunctionInfo ? DefaultedInfo : nullptr;
3044e5dd7070Spatrick }
3045e5dd7070Spatrick
hasBody(const FunctionDecl * & Definition) const3046e5dd7070Spatrick bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const {
3047*12c85518Srobert for (auto *I : redecls()) {
3048e5dd7070Spatrick if (I->doesThisDeclarationHaveABody()) {
3049e5dd7070Spatrick Definition = I;
3050e5dd7070Spatrick return true;
3051e5dd7070Spatrick }
3052e5dd7070Spatrick }
3053e5dd7070Spatrick
3054e5dd7070Spatrick return false;
3055e5dd7070Spatrick }
3056e5dd7070Spatrick
hasTrivialBody() const3057e5dd7070Spatrick bool FunctionDecl::hasTrivialBody() const {
3058e5dd7070Spatrick Stmt *S = getBody();
3059e5dd7070Spatrick if (!S) {
3060e5dd7070Spatrick // Since we don't have a body for this function, we don't know if it's
3061e5dd7070Spatrick // trivial or not.
3062e5dd7070Spatrick return false;
3063e5dd7070Spatrick }
3064e5dd7070Spatrick
3065e5dd7070Spatrick if (isa<CompoundStmt>(S) && cast<CompoundStmt>(S)->body_empty())
3066e5dd7070Spatrick return true;
3067e5dd7070Spatrick return false;
3068e5dd7070Spatrick }
3069e5dd7070Spatrick
isThisDeclarationInstantiatedFromAFriendDefinition() const3070a9ac8606Spatrick bool FunctionDecl::isThisDeclarationInstantiatedFromAFriendDefinition() const {
3071a9ac8606Spatrick if (!getFriendObjectKind())
3072a9ac8606Spatrick return false;
3073a9ac8606Spatrick
3074a9ac8606Spatrick // Check for a friend function instantiated from a friend function
3075a9ac8606Spatrick // definition in a templated class.
3076a9ac8606Spatrick if (const FunctionDecl *InstantiatedFrom =
3077a9ac8606Spatrick getInstantiatedFromMemberFunction())
3078a9ac8606Spatrick return InstantiatedFrom->getFriendObjectKind() &&
3079a9ac8606Spatrick InstantiatedFrom->isThisDeclarationADefinition();
3080a9ac8606Spatrick
3081a9ac8606Spatrick // Check for a friend function template instantiated from a friend
3082a9ac8606Spatrick // function template definition in a templated class.
3083a9ac8606Spatrick if (const FunctionTemplateDecl *Template = getDescribedFunctionTemplate()) {
3084a9ac8606Spatrick if (const FunctionTemplateDecl *InstantiatedFrom =
3085a9ac8606Spatrick Template->getInstantiatedFromMemberTemplate())
3086a9ac8606Spatrick return InstantiatedFrom->getFriendObjectKind() &&
3087a9ac8606Spatrick InstantiatedFrom->isThisDeclarationADefinition();
3088a9ac8606Spatrick }
3089a9ac8606Spatrick
3090a9ac8606Spatrick return false;
3091a9ac8606Spatrick }
3092a9ac8606Spatrick
isDefined(const FunctionDecl * & Definition,bool CheckForPendingFriendDefinition) const3093a9ac8606Spatrick bool FunctionDecl::isDefined(const FunctionDecl *&Definition,
3094a9ac8606Spatrick bool CheckForPendingFriendDefinition) const {
3095a9ac8606Spatrick for (const FunctionDecl *FD : redecls()) {
3096a9ac8606Spatrick if (FD->isThisDeclarationADefinition()) {
3097a9ac8606Spatrick Definition = FD;
3098a9ac8606Spatrick return true;
3099a9ac8606Spatrick }
3100a9ac8606Spatrick
3101a9ac8606Spatrick // If this is a friend function defined in a class template, it does not
3102a9ac8606Spatrick // have a body until it is used, nevertheless it is a definition, see
3103a9ac8606Spatrick // [temp.inst]p2:
3104a9ac8606Spatrick //
3105a9ac8606Spatrick // ... for the purpose of determining whether an instantiated redeclaration
3106a9ac8606Spatrick // is valid according to [basic.def.odr] and [class.mem], a declaration that
3107a9ac8606Spatrick // corresponds to a definition in the template is considered to be a
3108a9ac8606Spatrick // definition.
3109a9ac8606Spatrick //
3110a9ac8606Spatrick // The following code must produce redefinition error:
3111a9ac8606Spatrick //
3112a9ac8606Spatrick // template<typename T> struct C20 { friend void func_20() {} };
3113a9ac8606Spatrick // C20<int> c20i;
3114a9ac8606Spatrick // void func_20() {}
3115a9ac8606Spatrick //
3116a9ac8606Spatrick if (CheckForPendingFriendDefinition &&
3117a9ac8606Spatrick FD->isThisDeclarationInstantiatedFromAFriendDefinition()) {
3118a9ac8606Spatrick Definition = FD;
3119e5dd7070Spatrick return true;
3120e5dd7070Spatrick }
3121e5dd7070Spatrick }
3122e5dd7070Spatrick
3123e5dd7070Spatrick return false;
3124e5dd7070Spatrick }
3125e5dd7070Spatrick
getBody(const FunctionDecl * & Definition) const3126e5dd7070Spatrick Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
3127e5dd7070Spatrick if (!hasBody(Definition))
3128e5dd7070Spatrick return nullptr;
3129e5dd7070Spatrick
3130e5dd7070Spatrick assert(!Definition->FunctionDeclBits.HasDefaultedFunctionInfo &&
3131e5dd7070Spatrick "definition should not have a body");
3132e5dd7070Spatrick if (Definition->Body)
3133e5dd7070Spatrick return Definition->Body.get(getASTContext().getExternalSource());
3134e5dd7070Spatrick
3135e5dd7070Spatrick return nullptr;
3136e5dd7070Spatrick }
3137e5dd7070Spatrick
setBody(Stmt * B)3138e5dd7070Spatrick void FunctionDecl::setBody(Stmt *B) {
3139e5dd7070Spatrick FunctionDeclBits.HasDefaultedFunctionInfo = false;
3140e5dd7070Spatrick Body = LazyDeclStmtPtr(B);
3141e5dd7070Spatrick if (B)
3142e5dd7070Spatrick EndRangeLoc = B->getEndLoc();
3143e5dd7070Spatrick }
3144e5dd7070Spatrick
setPure(bool P)3145e5dd7070Spatrick void FunctionDecl::setPure(bool P) {
3146e5dd7070Spatrick FunctionDeclBits.IsPure = P;
3147e5dd7070Spatrick if (P)
3148e5dd7070Spatrick if (auto *Parent = dyn_cast<CXXRecordDecl>(getDeclContext()))
3149e5dd7070Spatrick Parent->markedVirtualFunctionPure();
3150e5dd7070Spatrick }
3151e5dd7070Spatrick
3152e5dd7070Spatrick template<std::size_t Len>
isNamed(const NamedDecl * ND,const char (& Str)[Len])3153e5dd7070Spatrick static bool isNamed(const NamedDecl *ND, const char (&Str)[Len]) {
3154e5dd7070Spatrick IdentifierInfo *II = ND->getIdentifier();
3155e5dd7070Spatrick return II && II->isStr(Str);
3156e5dd7070Spatrick }
3157e5dd7070Spatrick
isMain() const3158e5dd7070Spatrick bool FunctionDecl::isMain() const {
3159e5dd7070Spatrick const TranslationUnitDecl *tunit =
3160e5dd7070Spatrick dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext());
3161e5dd7070Spatrick return tunit &&
3162e5dd7070Spatrick !tunit->getASTContext().getLangOpts().Freestanding &&
3163e5dd7070Spatrick isNamed(this, "main");
3164e5dd7070Spatrick }
3165e5dd7070Spatrick
isMSVCRTEntryPoint() const3166e5dd7070Spatrick bool FunctionDecl::isMSVCRTEntryPoint() const {
3167e5dd7070Spatrick const TranslationUnitDecl *TUnit =
3168e5dd7070Spatrick dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext());
3169e5dd7070Spatrick if (!TUnit)
3170e5dd7070Spatrick return false;
3171e5dd7070Spatrick
3172e5dd7070Spatrick // Even though we aren't really targeting MSVCRT if we are freestanding,
3173e5dd7070Spatrick // semantic analysis for these functions remains the same.
3174e5dd7070Spatrick
3175e5dd7070Spatrick // MSVCRT entry points only exist on MSVCRT targets.
3176e5dd7070Spatrick if (!TUnit->getASTContext().getTargetInfo().getTriple().isOSMSVCRT())
3177e5dd7070Spatrick return false;
3178e5dd7070Spatrick
3179e5dd7070Spatrick // Nameless functions like constructors cannot be entry points.
3180e5dd7070Spatrick if (!getIdentifier())
3181e5dd7070Spatrick return false;
3182e5dd7070Spatrick
3183e5dd7070Spatrick return llvm::StringSwitch<bool>(getName())
3184e5dd7070Spatrick .Cases("main", // an ANSI console app
3185e5dd7070Spatrick "wmain", // a Unicode console App
3186e5dd7070Spatrick "WinMain", // an ANSI GUI app
3187e5dd7070Spatrick "wWinMain", // a Unicode GUI app
3188e5dd7070Spatrick "DllMain", // a DLL
3189e5dd7070Spatrick true)
3190e5dd7070Spatrick .Default(false);
3191e5dd7070Spatrick }
3192e5dd7070Spatrick
isReservedGlobalPlacementOperator() const3193e5dd7070Spatrick bool FunctionDecl::isReservedGlobalPlacementOperator() const {
3194*12c85518Srobert if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName)
3195*12c85518Srobert return false;
3196*12c85518Srobert if (getDeclName().getCXXOverloadedOperator() != OO_New &&
3197*12c85518Srobert getDeclName().getCXXOverloadedOperator() != OO_Delete &&
3198*12c85518Srobert getDeclName().getCXXOverloadedOperator() != OO_Array_New &&
3199*12c85518Srobert getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
3200*12c85518Srobert return false;
3201e5dd7070Spatrick
3202e5dd7070Spatrick if (!getDeclContext()->getRedeclContext()->isTranslationUnit())
3203e5dd7070Spatrick return false;
3204e5dd7070Spatrick
3205e5dd7070Spatrick const auto *proto = getType()->castAs<FunctionProtoType>();
3206e5dd7070Spatrick if (proto->getNumParams() != 2 || proto->isVariadic())
3207e5dd7070Spatrick return false;
3208e5dd7070Spatrick
3209e5dd7070Spatrick ASTContext &Context =
3210e5dd7070Spatrick cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext())
3211e5dd7070Spatrick ->getASTContext();
3212e5dd7070Spatrick
3213e5dd7070Spatrick // The result type and first argument type are constant across all
3214e5dd7070Spatrick // these operators. The second argument must be exactly void*.
3215e5dd7070Spatrick return (proto->getParamType(1).getCanonicalType() == Context.VoidPtrTy);
3216e5dd7070Spatrick }
3217e5dd7070Spatrick
isReplaceableGlobalAllocationFunction(std::optional<unsigned> * AlignmentParam,bool * IsNothrow) const3218ec727ea7Spatrick bool FunctionDecl::isReplaceableGlobalAllocationFunction(
3219*12c85518Srobert std::optional<unsigned> *AlignmentParam, bool *IsNothrow) const {
3220e5dd7070Spatrick if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName)
3221e5dd7070Spatrick return false;
3222e5dd7070Spatrick if (getDeclName().getCXXOverloadedOperator() != OO_New &&
3223e5dd7070Spatrick getDeclName().getCXXOverloadedOperator() != OO_Delete &&
3224e5dd7070Spatrick getDeclName().getCXXOverloadedOperator() != OO_Array_New &&
3225e5dd7070Spatrick getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
3226e5dd7070Spatrick return false;
3227e5dd7070Spatrick
3228e5dd7070Spatrick if (isa<CXXRecordDecl>(getDeclContext()))
3229e5dd7070Spatrick return false;
3230e5dd7070Spatrick
3231e5dd7070Spatrick // This can only fail for an invalid 'operator new' declaration.
3232e5dd7070Spatrick if (!getDeclContext()->getRedeclContext()->isTranslationUnit())
3233e5dd7070Spatrick return false;
3234e5dd7070Spatrick
3235e5dd7070Spatrick const auto *FPT = getType()->castAs<FunctionProtoType>();
3236e5dd7070Spatrick if (FPT->getNumParams() == 0 || FPT->getNumParams() > 3 || FPT->isVariadic())
3237e5dd7070Spatrick return false;
3238e5dd7070Spatrick
3239e5dd7070Spatrick // If this is a single-parameter function, it must be a replaceable global
3240e5dd7070Spatrick // allocation or deallocation function.
3241e5dd7070Spatrick if (FPT->getNumParams() == 1)
3242e5dd7070Spatrick return true;
3243e5dd7070Spatrick
3244e5dd7070Spatrick unsigned Params = 1;
3245e5dd7070Spatrick QualType Ty = FPT->getParamType(Params);
3246e5dd7070Spatrick ASTContext &Ctx = getASTContext();
3247e5dd7070Spatrick
3248e5dd7070Spatrick auto Consume = [&] {
3249e5dd7070Spatrick ++Params;
3250e5dd7070Spatrick Ty = Params < FPT->getNumParams() ? FPT->getParamType(Params) : QualType();
3251e5dd7070Spatrick };
3252e5dd7070Spatrick
3253e5dd7070Spatrick // In C++14, the next parameter can be a 'std::size_t' for sized delete.
3254e5dd7070Spatrick bool IsSizedDelete = false;
3255e5dd7070Spatrick if (Ctx.getLangOpts().SizedDeallocation &&
3256e5dd7070Spatrick (getDeclName().getCXXOverloadedOperator() == OO_Delete ||
3257e5dd7070Spatrick getDeclName().getCXXOverloadedOperator() == OO_Array_Delete) &&
3258e5dd7070Spatrick Ctx.hasSameType(Ty, Ctx.getSizeType())) {
3259e5dd7070Spatrick IsSizedDelete = true;
3260e5dd7070Spatrick Consume();
3261e5dd7070Spatrick }
3262e5dd7070Spatrick
3263e5dd7070Spatrick // In C++17, the next parameter can be a 'std::align_val_t' for aligned
3264e5dd7070Spatrick // new/delete.
3265e5dd7070Spatrick if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT()) {
3266e5dd7070Spatrick Consume();
3267ec727ea7Spatrick if (AlignmentParam)
3268ec727ea7Spatrick *AlignmentParam = Params;
3269e5dd7070Spatrick }
3270e5dd7070Spatrick
3271e5dd7070Spatrick // Finally, if this is not a sized delete, the final parameter can
3272e5dd7070Spatrick // be a 'const std::nothrow_t&'.
3273e5dd7070Spatrick if (!IsSizedDelete && !Ty.isNull() && Ty->isReferenceType()) {
3274e5dd7070Spatrick Ty = Ty->getPointeeType();
3275e5dd7070Spatrick if (Ty.getCVRQualifiers() != Qualifiers::Const)
3276e5dd7070Spatrick return false;
3277ec727ea7Spatrick if (Ty->isNothrowT()) {
3278ec727ea7Spatrick if (IsNothrow)
3279ec727ea7Spatrick *IsNothrow = true;
3280e5dd7070Spatrick Consume();
3281e5dd7070Spatrick }
3282ec727ea7Spatrick }
3283e5dd7070Spatrick
3284e5dd7070Spatrick return Params == FPT->getNumParams();
3285e5dd7070Spatrick }
3286e5dd7070Spatrick
isInlineBuiltinDeclaration() const3287e5dd7070Spatrick bool FunctionDecl::isInlineBuiltinDeclaration() const {
3288e5dd7070Spatrick if (!getBuiltinID())
3289e5dd7070Spatrick return false;
3290e5dd7070Spatrick
3291e5dd7070Spatrick const FunctionDecl *Definition;
3292*12c85518Srobert return hasBody(Definition) && Definition->isInlineSpecified() &&
3293*12c85518Srobert Definition->hasAttr<AlwaysInlineAttr>() &&
3294*12c85518Srobert Definition->hasAttr<GNUInlineAttr>();
3295e5dd7070Spatrick }
3296e5dd7070Spatrick
isDestroyingOperatorDelete() const3297e5dd7070Spatrick bool FunctionDecl::isDestroyingOperatorDelete() const {
3298e5dd7070Spatrick // C++ P0722:
3299e5dd7070Spatrick // Within a class C, a single object deallocation function with signature
3300e5dd7070Spatrick // (T, std::destroying_delete_t, <more params>)
3301e5dd7070Spatrick // is a destroying operator delete.
3302e5dd7070Spatrick if (!isa<CXXMethodDecl>(this) || getOverloadedOperator() != OO_Delete ||
3303e5dd7070Spatrick getNumParams() < 2)
3304e5dd7070Spatrick return false;
3305e5dd7070Spatrick
3306e5dd7070Spatrick auto *RD = getParamDecl(1)->getType()->getAsCXXRecordDecl();
3307e5dd7070Spatrick return RD && RD->isInStdNamespace() && RD->getIdentifier() &&
3308e5dd7070Spatrick RD->getIdentifier()->isStr("destroying_delete_t");
3309e5dd7070Spatrick }
3310e5dd7070Spatrick
getLanguageLinkage() const3311e5dd7070Spatrick LanguageLinkage FunctionDecl::getLanguageLinkage() const {
3312e5dd7070Spatrick return getDeclLanguageLinkage(*this);
3313e5dd7070Spatrick }
3314e5dd7070Spatrick
isExternC() const3315e5dd7070Spatrick bool FunctionDecl::isExternC() const {
3316e5dd7070Spatrick return isDeclExternC(*this);
3317e5dd7070Spatrick }
3318e5dd7070Spatrick
isInExternCContext() const3319e5dd7070Spatrick bool FunctionDecl::isInExternCContext() const {
3320e5dd7070Spatrick if (hasAttr<OpenCLKernelAttr>())
3321e5dd7070Spatrick return true;
3322e5dd7070Spatrick return getLexicalDeclContext()->isExternCContext();
3323e5dd7070Spatrick }
3324e5dd7070Spatrick
isInExternCXXContext() const3325e5dd7070Spatrick bool FunctionDecl::isInExternCXXContext() const {
3326e5dd7070Spatrick return getLexicalDeclContext()->isExternCXXContext();
3327e5dd7070Spatrick }
3328e5dd7070Spatrick
isGlobal() const3329e5dd7070Spatrick bool FunctionDecl::isGlobal() const {
3330e5dd7070Spatrick if (const auto *Method = dyn_cast<CXXMethodDecl>(this))
3331e5dd7070Spatrick return Method->isStatic();
3332e5dd7070Spatrick
3333e5dd7070Spatrick if (getCanonicalDecl()->getStorageClass() == SC_Static)
3334e5dd7070Spatrick return false;
3335e5dd7070Spatrick
3336e5dd7070Spatrick for (const DeclContext *DC = getDeclContext();
3337e5dd7070Spatrick DC->isNamespace();
3338e5dd7070Spatrick DC = DC->getParent()) {
3339e5dd7070Spatrick if (const auto *Namespace = cast<NamespaceDecl>(DC)) {
3340e5dd7070Spatrick if (!Namespace->getDeclName())
3341e5dd7070Spatrick return false;
3342e5dd7070Spatrick }
3343e5dd7070Spatrick }
3344e5dd7070Spatrick
3345e5dd7070Spatrick return true;
3346e5dd7070Spatrick }
3347e5dd7070Spatrick
isNoReturn() const3348e5dd7070Spatrick bool FunctionDecl::isNoReturn() const {
3349e5dd7070Spatrick if (hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() ||
3350e5dd7070Spatrick hasAttr<C11NoReturnAttr>())
3351e5dd7070Spatrick return true;
3352e5dd7070Spatrick
3353e5dd7070Spatrick if (auto *FnTy = getType()->getAs<FunctionType>())
3354e5dd7070Spatrick return FnTy->getNoReturnAttr();
3355e5dd7070Spatrick
3356e5dd7070Spatrick return false;
3357e5dd7070Spatrick }
3358e5dd7070Spatrick
3359e5dd7070Spatrick
getMultiVersionKind() const3360e5dd7070Spatrick MultiVersionKind FunctionDecl::getMultiVersionKind() const {
3361e5dd7070Spatrick if (hasAttr<TargetAttr>())
3362e5dd7070Spatrick return MultiVersionKind::Target;
3363*12c85518Srobert if (hasAttr<TargetVersionAttr>())
3364*12c85518Srobert return MultiVersionKind::TargetVersion;
3365e5dd7070Spatrick if (hasAttr<CPUDispatchAttr>())
3366e5dd7070Spatrick return MultiVersionKind::CPUDispatch;
3367e5dd7070Spatrick if (hasAttr<CPUSpecificAttr>())
3368e5dd7070Spatrick return MultiVersionKind::CPUSpecific;
3369*12c85518Srobert if (hasAttr<TargetClonesAttr>())
3370*12c85518Srobert return MultiVersionKind::TargetClones;
3371e5dd7070Spatrick return MultiVersionKind::None;
3372e5dd7070Spatrick }
3373e5dd7070Spatrick
isCPUDispatchMultiVersion() const3374e5dd7070Spatrick bool FunctionDecl::isCPUDispatchMultiVersion() const {
3375e5dd7070Spatrick return isMultiVersion() && hasAttr<CPUDispatchAttr>();
3376e5dd7070Spatrick }
3377e5dd7070Spatrick
isCPUSpecificMultiVersion() const3378e5dd7070Spatrick bool FunctionDecl::isCPUSpecificMultiVersion() const {
3379e5dd7070Spatrick return isMultiVersion() && hasAttr<CPUSpecificAttr>();
3380e5dd7070Spatrick }
3381e5dd7070Spatrick
isTargetMultiVersion() const3382e5dd7070Spatrick bool FunctionDecl::isTargetMultiVersion() const {
3383*12c85518Srobert return isMultiVersion() &&
3384*12c85518Srobert (hasAttr<TargetAttr>() || hasAttr<TargetVersionAttr>());
3385*12c85518Srobert }
3386*12c85518Srobert
isTargetClonesMultiVersion() const3387*12c85518Srobert bool FunctionDecl::isTargetClonesMultiVersion() const {
3388*12c85518Srobert return isMultiVersion() && hasAttr<TargetClonesAttr>();
3389e5dd7070Spatrick }
3390e5dd7070Spatrick
3391e5dd7070Spatrick void
setPreviousDeclaration(FunctionDecl * PrevDecl)3392e5dd7070Spatrick FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
3393e5dd7070Spatrick redeclarable_base::setPreviousDecl(PrevDecl);
3394e5dd7070Spatrick
3395e5dd7070Spatrick if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
3396e5dd7070Spatrick FunctionTemplateDecl *PrevFunTmpl
3397e5dd7070Spatrick = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : nullptr;
3398e5dd7070Spatrick assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch");
3399e5dd7070Spatrick FunTmpl->setPreviousDecl(PrevFunTmpl);
3400e5dd7070Spatrick }
3401e5dd7070Spatrick
3402e5dd7070Spatrick if (PrevDecl && PrevDecl->isInlined())
3403e5dd7070Spatrick setImplicitlyInline(true);
3404e5dd7070Spatrick }
3405e5dd7070Spatrick
getCanonicalDecl()3406e5dd7070Spatrick FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); }
3407e5dd7070Spatrick
3408e5dd7070Spatrick /// Returns a value indicating whether this function corresponds to a builtin
3409e5dd7070Spatrick /// function.
3410e5dd7070Spatrick ///
3411e5dd7070Spatrick /// The function corresponds to a built-in function if it is declared at
3412e5dd7070Spatrick /// translation scope or within an extern "C" block and its name matches with
3413e5dd7070Spatrick /// the name of a builtin. The returned value will be 0 for functions that do
3414e5dd7070Spatrick /// not correspond to a builtin, a value of type \c Builtin::ID if in the
3415e5dd7070Spatrick /// target-independent range \c [1,Builtin::First), or a target-specific builtin
3416e5dd7070Spatrick /// value.
3417e5dd7070Spatrick ///
3418e5dd7070Spatrick /// \param ConsiderWrapperFunctions If true, we should consider wrapper
3419e5dd7070Spatrick /// functions as their wrapped builtins. This shouldn't be done in general, but
3420e5dd7070Spatrick /// it's useful in Sema to diagnose calls to wrappers based on their semantics.
getBuiltinID(bool ConsiderWrapperFunctions) const3421e5dd7070Spatrick unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const {
3422ec727ea7Spatrick unsigned BuiltinID = 0;
3423e5dd7070Spatrick
3424ec727ea7Spatrick if (const auto *ABAA = getAttr<ArmBuiltinAliasAttr>()) {
3425ec727ea7Spatrick BuiltinID = ABAA->getBuiltinName()->getBuiltinID();
3426a9ac8606Spatrick } else if (const auto *BAA = getAttr<BuiltinAliasAttr>()) {
3427a9ac8606Spatrick BuiltinID = BAA->getBuiltinName()->getBuiltinID();
3428ec727ea7Spatrick } else if (const auto *A = getAttr<BuiltinAttr>()) {
3429ec727ea7Spatrick BuiltinID = A->getID();
3430e5dd7070Spatrick }
3431e5dd7070Spatrick
3432e5dd7070Spatrick if (!BuiltinID)
3433e5dd7070Spatrick return 0;
3434e5dd7070Spatrick
3435e5dd7070Spatrick // If the function is marked "overloadable", it has a different mangled name
3436e5dd7070Spatrick // and is not the C library function.
3437e5dd7070Spatrick if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>() &&
3438a9ac8606Spatrick (!hasAttr<ArmBuiltinAliasAttr>() && !hasAttr<BuiltinAliasAttr>()))
3439e5dd7070Spatrick return 0;
3440e5dd7070Spatrick
3441ec727ea7Spatrick ASTContext &Context = getASTContext();
3442e5dd7070Spatrick if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
3443e5dd7070Spatrick return BuiltinID;
3444e5dd7070Spatrick
3445e5dd7070Spatrick // This function has the name of a known C library
3446e5dd7070Spatrick // function. Determine whether it actually refers to the C library
3447e5dd7070Spatrick // function or whether it just has the same name.
3448e5dd7070Spatrick
3449e5dd7070Spatrick // If this is a static function, it's not a builtin.
3450e5dd7070Spatrick if (!ConsiderWrapperFunctions && getStorageClass() == SC_Static)
3451e5dd7070Spatrick return 0;
3452e5dd7070Spatrick
3453e5dd7070Spatrick // OpenCL v1.2 s6.9.f - The library functions defined in
3454e5dd7070Spatrick // the C99 standard headers are not available.
3455e5dd7070Spatrick if (Context.getLangOpts().OpenCL &&
3456e5dd7070Spatrick Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
3457e5dd7070Spatrick return 0;
3458e5dd7070Spatrick
3459e5dd7070Spatrick // CUDA does not have device-side standard library. printf and malloc are the
3460e5dd7070Spatrick // only special cases that are supported by device-side runtime.
3461e5dd7070Spatrick if (Context.getLangOpts().CUDA && hasAttr<CUDADeviceAttr>() &&
3462e5dd7070Spatrick !hasAttr<CUDAHostAttr>() &&
3463e5dd7070Spatrick !(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc))
3464e5dd7070Spatrick return 0;
3465e5dd7070Spatrick
3466ec727ea7Spatrick // As AMDGCN implementation of OpenMP does not have a device-side standard
3467ec727ea7Spatrick // library, none of the predefined library functions except printf and malloc
3468ec727ea7Spatrick // should be treated as a builtin i.e. 0 should be returned for them.
3469ec727ea7Spatrick if (Context.getTargetInfo().getTriple().isAMDGCN() &&
3470ec727ea7Spatrick Context.getLangOpts().OpenMPIsDevice &&
3471ec727ea7Spatrick Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) &&
3472ec727ea7Spatrick !(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc))
3473ec727ea7Spatrick return 0;
3474ec727ea7Spatrick
3475e5dd7070Spatrick return BuiltinID;
3476e5dd7070Spatrick }
3477e5dd7070Spatrick
3478e5dd7070Spatrick /// getNumParams - Return the number of parameters this function must have
3479e5dd7070Spatrick /// based on its FunctionType. This is the length of the ParamInfo array
3480e5dd7070Spatrick /// after it has been created.
getNumParams() const3481e5dd7070Spatrick unsigned FunctionDecl::getNumParams() const {
3482e5dd7070Spatrick const auto *FPT = getType()->getAs<FunctionProtoType>();
3483e5dd7070Spatrick return FPT ? FPT->getNumParams() : 0;
3484e5dd7070Spatrick }
3485e5dd7070Spatrick
setParams(ASTContext & C,ArrayRef<ParmVarDecl * > NewParamInfo)3486e5dd7070Spatrick void FunctionDecl::setParams(ASTContext &C,
3487e5dd7070Spatrick ArrayRef<ParmVarDecl *> NewParamInfo) {
3488e5dd7070Spatrick assert(!ParamInfo && "Already has param info!");
3489e5dd7070Spatrick assert(NewParamInfo.size() == getNumParams() && "Parameter count mismatch!");
3490e5dd7070Spatrick
3491e5dd7070Spatrick // Zero params -> null pointer.
3492e5dd7070Spatrick if (!NewParamInfo.empty()) {
3493e5dd7070Spatrick ParamInfo = new (C) ParmVarDecl*[NewParamInfo.size()];
3494e5dd7070Spatrick std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo);
3495e5dd7070Spatrick }
3496e5dd7070Spatrick }
3497e5dd7070Spatrick
3498e5dd7070Spatrick /// getMinRequiredArguments - Returns the minimum number of arguments
3499e5dd7070Spatrick /// needed to call this function. This may be fewer than the number of
3500e5dd7070Spatrick /// function parameters, if some of the parameters have default
3501e5dd7070Spatrick /// arguments (in C++) or are parameter packs (C++11).
getMinRequiredArguments() const3502e5dd7070Spatrick unsigned FunctionDecl::getMinRequiredArguments() const {
3503e5dd7070Spatrick if (!getASTContext().getLangOpts().CPlusPlus)
3504e5dd7070Spatrick return getNumParams();
3505e5dd7070Spatrick
3506ec727ea7Spatrick // Note that it is possible for a parameter with no default argument to
3507ec727ea7Spatrick // follow a parameter with a default argument.
3508e5dd7070Spatrick unsigned NumRequiredArgs = 0;
3509ec727ea7Spatrick unsigned MinParamsSoFar = 0;
3510ec727ea7Spatrick for (auto *Param : parameters()) {
3511ec727ea7Spatrick if (!Param->isParameterPack()) {
3512ec727ea7Spatrick ++MinParamsSoFar;
3513ec727ea7Spatrick if (!Param->hasDefaultArg())
3514ec727ea7Spatrick NumRequiredArgs = MinParamsSoFar;
3515ec727ea7Spatrick }
3516ec727ea7Spatrick }
3517e5dd7070Spatrick return NumRequiredArgs;
3518e5dd7070Spatrick }
3519e5dd7070Spatrick
hasOneParamOrDefaultArgs() const3520ec727ea7Spatrick bool FunctionDecl::hasOneParamOrDefaultArgs() const {
3521ec727ea7Spatrick return getNumParams() == 1 ||
3522ec727ea7Spatrick (getNumParams() > 1 &&
3523*12c85518Srobert llvm::all_of(llvm::drop_begin(parameters()),
3524ec727ea7Spatrick [](ParmVarDecl *P) { return P->hasDefaultArg(); }));
3525ec727ea7Spatrick }
3526ec727ea7Spatrick
3527e5dd7070Spatrick /// The combination of the extern and inline keywords under MSVC forces
3528e5dd7070Spatrick /// the function to be required.
3529e5dd7070Spatrick ///
3530e5dd7070Spatrick /// Note: This function assumes that we will only get called when isInlined()
3531e5dd7070Spatrick /// would return true for this FunctionDecl.
isMSExternInline() const3532e5dd7070Spatrick bool FunctionDecl::isMSExternInline() const {
3533e5dd7070Spatrick assert(isInlined() && "expected to get called on an inlined function!");
3534e5dd7070Spatrick
3535e5dd7070Spatrick const ASTContext &Context = getASTContext();
3536e5dd7070Spatrick if (!Context.getTargetInfo().getCXXABI().isMicrosoft() &&
3537e5dd7070Spatrick !hasAttr<DLLExportAttr>())
3538e5dd7070Spatrick return false;
3539e5dd7070Spatrick
3540e5dd7070Spatrick for (const FunctionDecl *FD = getMostRecentDecl(); FD;
3541e5dd7070Spatrick FD = FD->getPreviousDecl())
3542e5dd7070Spatrick if (!FD->isImplicit() && FD->getStorageClass() == SC_Extern)
3543e5dd7070Spatrick return true;
3544e5dd7070Spatrick
3545e5dd7070Spatrick return false;
3546e5dd7070Spatrick }
3547e5dd7070Spatrick
redeclForcesDefMSVC(const FunctionDecl * Redecl)3548e5dd7070Spatrick static bool redeclForcesDefMSVC(const FunctionDecl *Redecl) {
3549e5dd7070Spatrick if (Redecl->getStorageClass() != SC_Extern)
3550e5dd7070Spatrick return false;
3551e5dd7070Spatrick
3552e5dd7070Spatrick for (const FunctionDecl *FD = Redecl->getPreviousDecl(); FD;
3553e5dd7070Spatrick FD = FD->getPreviousDecl())
3554e5dd7070Spatrick if (!FD->isImplicit() && FD->getStorageClass() == SC_Extern)
3555e5dd7070Spatrick return false;
3556e5dd7070Spatrick
3557e5dd7070Spatrick return true;
3558e5dd7070Spatrick }
3559e5dd7070Spatrick
RedeclForcesDefC99(const FunctionDecl * Redecl)3560e5dd7070Spatrick static bool RedeclForcesDefC99(const FunctionDecl *Redecl) {
3561e5dd7070Spatrick // Only consider file-scope declarations in this test.
3562e5dd7070Spatrick if (!Redecl->getLexicalDeclContext()->isTranslationUnit())
3563e5dd7070Spatrick return false;
3564e5dd7070Spatrick
3565e5dd7070Spatrick // Only consider explicit declarations; the presence of a builtin for a
3566e5dd7070Spatrick // libcall shouldn't affect whether a definition is externally visible.
3567e5dd7070Spatrick if (Redecl->isImplicit())
3568e5dd7070Spatrick return false;
3569e5dd7070Spatrick
3570e5dd7070Spatrick if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern)
3571e5dd7070Spatrick return true; // Not an inline definition
3572e5dd7070Spatrick
3573e5dd7070Spatrick return false;
3574e5dd7070Spatrick }
3575e5dd7070Spatrick
3576e5dd7070Spatrick /// For a function declaration in C or C++, determine whether this
3577e5dd7070Spatrick /// declaration causes the definition to be externally visible.
3578e5dd7070Spatrick ///
3579e5dd7070Spatrick /// For instance, this determines if adding the current declaration to the set
3580e5dd7070Spatrick /// of redeclarations of the given functions causes
3581e5dd7070Spatrick /// isInlineDefinitionExternallyVisible to change from false to true.
doesDeclarationForceExternallyVisibleDefinition() const3582e5dd7070Spatrick bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const {
3583e5dd7070Spatrick assert(!doesThisDeclarationHaveABody() &&
3584e5dd7070Spatrick "Must have a declaration without a body.");
3585e5dd7070Spatrick
3586e5dd7070Spatrick ASTContext &Context = getASTContext();
3587e5dd7070Spatrick
3588e5dd7070Spatrick if (Context.getLangOpts().MSVCCompat) {
3589e5dd7070Spatrick const FunctionDecl *Definition;
3590e5dd7070Spatrick if (hasBody(Definition) && Definition->isInlined() &&
3591e5dd7070Spatrick redeclForcesDefMSVC(this))
3592e5dd7070Spatrick return true;
3593e5dd7070Spatrick }
3594e5dd7070Spatrick
3595e5dd7070Spatrick if (Context.getLangOpts().CPlusPlus)
3596e5dd7070Spatrick return false;
3597e5dd7070Spatrick
3598e5dd7070Spatrick if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) {
3599e5dd7070Spatrick // With GNU inlining, a declaration with 'inline' but not 'extern', forces
3600e5dd7070Spatrick // an externally visible definition.
3601e5dd7070Spatrick //
3602e5dd7070Spatrick // FIXME: What happens if gnu_inline gets added on after the first
3603e5dd7070Spatrick // declaration?
3604e5dd7070Spatrick if (!isInlineSpecified() || getStorageClass() == SC_Extern)
3605e5dd7070Spatrick return false;
3606e5dd7070Spatrick
3607e5dd7070Spatrick const FunctionDecl *Prev = this;
3608e5dd7070Spatrick bool FoundBody = false;
3609e5dd7070Spatrick while ((Prev = Prev->getPreviousDecl())) {
3610e5dd7070Spatrick FoundBody |= Prev->doesThisDeclarationHaveABody();
3611e5dd7070Spatrick
3612e5dd7070Spatrick if (Prev->doesThisDeclarationHaveABody()) {
3613e5dd7070Spatrick // If it's not the case that both 'inline' and 'extern' are
3614e5dd7070Spatrick // specified on the definition, then it is always externally visible.
3615e5dd7070Spatrick if (!Prev->isInlineSpecified() ||
3616e5dd7070Spatrick Prev->getStorageClass() != SC_Extern)
3617e5dd7070Spatrick return false;
3618e5dd7070Spatrick } else if (Prev->isInlineSpecified() &&
3619e5dd7070Spatrick Prev->getStorageClass() != SC_Extern) {
3620e5dd7070Spatrick return false;
3621e5dd7070Spatrick }
3622e5dd7070Spatrick }
3623e5dd7070Spatrick return FoundBody;
3624e5dd7070Spatrick }
3625e5dd7070Spatrick
3626e5dd7070Spatrick // C99 6.7.4p6:
3627e5dd7070Spatrick // [...] If all of the file scope declarations for a function in a
3628e5dd7070Spatrick // translation unit include the inline function specifier without extern,
3629e5dd7070Spatrick // then the definition in that translation unit is an inline definition.
3630e5dd7070Spatrick if (isInlineSpecified() && getStorageClass() != SC_Extern)
3631e5dd7070Spatrick return false;
3632e5dd7070Spatrick const FunctionDecl *Prev = this;
3633e5dd7070Spatrick bool FoundBody = false;
3634e5dd7070Spatrick while ((Prev = Prev->getPreviousDecl())) {
3635e5dd7070Spatrick FoundBody |= Prev->doesThisDeclarationHaveABody();
3636e5dd7070Spatrick if (RedeclForcesDefC99(Prev))
3637e5dd7070Spatrick return false;
3638e5dd7070Spatrick }
3639e5dd7070Spatrick return FoundBody;
3640e5dd7070Spatrick }
3641e5dd7070Spatrick
getFunctionTypeLoc() const3642e5dd7070Spatrick FunctionTypeLoc FunctionDecl::getFunctionTypeLoc() const {
3643e5dd7070Spatrick const TypeSourceInfo *TSI = getTypeSourceInfo();
3644e5dd7070Spatrick return TSI ? TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>()
3645e5dd7070Spatrick : FunctionTypeLoc();
3646e5dd7070Spatrick }
3647e5dd7070Spatrick
getReturnTypeSourceRange() const3648e5dd7070Spatrick SourceRange FunctionDecl::getReturnTypeSourceRange() const {
3649e5dd7070Spatrick FunctionTypeLoc FTL = getFunctionTypeLoc();
3650e5dd7070Spatrick if (!FTL)
3651e5dd7070Spatrick return SourceRange();
3652e5dd7070Spatrick
3653e5dd7070Spatrick // Skip self-referential return types.
3654e5dd7070Spatrick const SourceManager &SM = getASTContext().getSourceManager();
3655e5dd7070Spatrick SourceRange RTRange = FTL.getReturnLoc().getSourceRange();
3656e5dd7070Spatrick SourceLocation Boundary = getNameInfo().getBeginLoc();
3657e5dd7070Spatrick if (RTRange.isInvalid() || Boundary.isInvalid() ||
3658e5dd7070Spatrick !SM.isBeforeInTranslationUnit(RTRange.getEnd(), Boundary))
3659e5dd7070Spatrick return SourceRange();
3660e5dd7070Spatrick
3661e5dd7070Spatrick return RTRange;
3662e5dd7070Spatrick }
3663e5dd7070Spatrick
getParametersSourceRange() const3664e5dd7070Spatrick SourceRange FunctionDecl::getParametersSourceRange() const {
3665e5dd7070Spatrick unsigned NP = getNumParams();
3666e5dd7070Spatrick SourceLocation EllipsisLoc = getEllipsisLoc();
3667e5dd7070Spatrick
3668e5dd7070Spatrick if (NP == 0 && EllipsisLoc.isInvalid())
3669e5dd7070Spatrick return SourceRange();
3670e5dd7070Spatrick
3671e5dd7070Spatrick SourceLocation Begin =
3672e5dd7070Spatrick NP > 0 ? ParamInfo[0]->getSourceRange().getBegin() : EllipsisLoc;
3673e5dd7070Spatrick SourceLocation End = EllipsisLoc.isValid()
3674e5dd7070Spatrick ? EllipsisLoc
3675e5dd7070Spatrick : ParamInfo[NP - 1]->getSourceRange().getEnd();
3676e5dd7070Spatrick
3677e5dd7070Spatrick return SourceRange(Begin, End);
3678e5dd7070Spatrick }
3679e5dd7070Spatrick
getExceptionSpecSourceRange() const3680e5dd7070Spatrick SourceRange FunctionDecl::getExceptionSpecSourceRange() const {
3681e5dd7070Spatrick FunctionTypeLoc FTL = getFunctionTypeLoc();
3682e5dd7070Spatrick return FTL ? FTL.getExceptionSpecRange() : SourceRange();
3683e5dd7070Spatrick }
3684e5dd7070Spatrick
3685e5dd7070Spatrick /// For an inline function definition in C, or for a gnu_inline function
3686e5dd7070Spatrick /// in C++, determine whether the definition will be externally visible.
3687e5dd7070Spatrick ///
3688e5dd7070Spatrick /// Inline function definitions are always available for inlining optimizations.
3689e5dd7070Spatrick /// However, depending on the language dialect, declaration specifiers, and
3690e5dd7070Spatrick /// attributes, the definition of an inline function may or may not be
3691e5dd7070Spatrick /// "externally" visible to other translation units in the program.
3692e5dd7070Spatrick ///
3693e5dd7070Spatrick /// In C99, inline definitions are not externally visible by default. However,
3694e5dd7070Spatrick /// if even one of the global-scope declarations is marked "extern inline", the
3695e5dd7070Spatrick /// inline definition becomes externally visible (C99 6.7.4p6).
3696e5dd7070Spatrick ///
3697e5dd7070Spatrick /// In GNU89 mode, or if the gnu_inline attribute is attached to the function
3698e5dd7070Spatrick /// definition, we use the GNU semantics for inline, which are nearly the
3699e5dd7070Spatrick /// opposite of C99 semantics. In particular, "inline" by itself will create
3700e5dd7070Spatrick /// an externally visible symbol, but "extern inline" will not create an
3701e5dd7070Spatrick /// externally visible symbol.
isInlineDefinitionExternallyVisible() const3702e5dd7070Spatrick bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
3703e5dd7070Spatrick assert((doesThisDeclarationHaveABody() || willHaveBody() ||
3704e5dd7070Spatrick hasAttr<AliasAttr>()) &&
3705e5dd7070Spatrick "Must be a function definition");
3706e5dd7070Spatrick assert(isInlined() && "Function must be inline");
3707e5dd7070Spatrick ASTContext &Context = getASTContext();
3708e5dd7070Spatrick
3709e5dd7070Spatrick if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) {
3710e5dd7070Spatrick // Note: If you change the logic here, please change
3711e5dd7070Spatrick // doesDeclarationForceExternallyVisibleDefinition as well.
3712e5dd7070Spatrick //
3713e5dd7070Spatrick // If it's not the case that both 'inline' and 'extern' are
3714e5dd7070Spatrick // specified on the definition, then this inline definition is
3715e5dd7070Spatrick // externally visible.
3716e5dd7070Spatrick if (Context.getLangOpts().CPlusPlus)
3717e5dd7070Spatrick return false;
3718e5dd7070Spatrick if (!(isInlineSpecified() && getStorageClass() == SC_Extern))
3719e5dd7070Spatrick return true;
3720e5dd7070Spatrick
3721e5dd7070Spatrick // If any declaration is 'inline' but not 'extern', then this definition
3722e5dd7070Spatrick // is externally visible.
3723*12c85518Srobert for (auto *Redecl : redecls()) {
3724e5dd7070Spatrick if (Redecl->isInlineSpecified() &&
3725e5dd7070Spatrick Redecl->getStorageClass() != SC_Extern)
3726e5dd7070Spatrick return true;
3727e5dd7070Spatrick }
3728e5dd7070Spatrick
3729e5dd7070Spatrick return false;
3730e5dd7070Spatrick }
3731e5dd7070Spatrick
3732e5dd7070Spatrick // The rest of this function is C-only.
3733e5dd7070Spatrick assert(!Context.getLangOpts().CPlusPlus &&
3734e5dd7070Spatrick "should not use C inline rules in C++");
3735e5dd7070Spatrick
3736e5dd7070Spatrick // C99 6.7.4p6:
3737e5dd7070Spatrick // [...] If all of the file scope declarations for a function in a
3738e5dd7070Spatrick // translation unit include the inline function specifier without extern,
3739e5dd7070Spatrick // then the definition in that translation unit is an inline definition.
3740*12c85518Srobert for (auto *Redecl : redecls()) {
3741e5dd7070Spatrick if (RedeclForcesDefC99(Redecl))
3742e5dd7070Spatrick return true;
3743e5dd7070Spatrick }
3744e5dd7070Spatrick
3745e5dd7070Spatrick // C99 6.7.4p6:
3746e5dd7070Spatrick // An inline definition does not provide an external definition for the
3747e5dd7070Spatrick // function, and does not forbid an external definition in another
3748e5dd7070Spatrick // translation unit.
3749e5dd7070Spatrick return false;
3750e5dd7070Spatrick }
3751e5dd7070Spatrick
3752e5dd7070Spatrick /// getOverloadedOperator - Which C++ overloaded operator this
3753e5dd7070Spatrick /// function represents, if any.
getOverloadedOperator() const3754e5dd7070Spatrick OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
3755e5dd7070Spatrick if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
3756e5dd7070Spatrick return getDeclName().getCXXOverloadedOperator();
3757e5dd7070Spatrick return OO_None;
3758e5dd7070Spatrick }
3759e5dd7070Spatrick
3760e5dd7070Spatrick /// getLiteralIdentifier - The literal suffix identifier this function
3761e5dd7070Spatrick /// represents, if any.
getLiteralIdentifier() const3762e5dd7070Spatrick const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const {
3763e5dd7070Spatrick if (getDeclName().getNameKind() == DeclarationName::CXXLiteralOperatorName)
3764e5dd7070Spatrick return getDeclName().getCXXLiteralIdentifier();
3765e5dd7070Spatrick return nullptr;
3766e5dd7070Spatrick }
3767e5dd7070Spatrick
getTemplatedKind() const3768e5dd7070Spatrick FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const {
3769e5dd7070Spatrick if (TemplateOrSpecialization.isNull())
3770e5dd7070Spatrick return TK_NonTemplate;
3771*12c85518Srobert if (const auto *ND = TemplateOrSpecialization.dyn_cast<NamedDecl *>()) {
3772*12c85518Srobert if (isa<FunctionDecl>(ND))
3773*12c85518Srobert return TK_DependentNonTemplate;
3774*12c85518Srobert assert(isa<FunctionTemplateDecl>(ND) &&
3775*12c85518Srobert "No other valid types in NamedDecl");
3776e5dd7070Spatrick return TK_FunctionTemplate;
3777*12c85518Srobert }
3778e5dd7070Spatrick if (TemplateOrSpecialization.is<MemberSpecializationInfo *>())
3779e5dd7070Spatrick return TK_MemberSpecialization;
3780e5dd7070Spatrick if (TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>())
3781e5dd7070Spatrick return TK_FunctionTemplateSpecialization;
3782e5dd7070Spatrick if (TemplateOrSpecialization.is
3783e5dd7070Spatrick <DependentFunctionTemplateSpecializationInfo*>())
3784e5dd7070Spatrick return TK_DependentFunctionTemplateSpecialization;
3785e5dd7070Spatrick
3786e5dd7070Spatrick llvm_unreachable("Did we miss a TemplateOrSpecialization type?");
3787e5dd7070Spatrick }
3788e5dd7070Spatrick
getInstantiatedFromMemberFunction() const3789e5dd7070Spatrick FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
3790e5dd7070Spatrick if (MemberSpecializationInfo *Info = getMemberSpecializationInfo())
3791e5dd7070Spatrick return cast<FunctionDecl>(Info->getInstantiatedFrom());
3792e5dd7070Spatrick
3793e5dd7070Spatrick return nullptr;
3794e5dd7070Spatrick }
3795e5dd7070Spatrick
getMemberSpecializationInfo() const3796e5dd7070Spatrick MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const {
3797e5dd7070Spatrick if (auto *MSI =
3798e5dd7070Spatrick TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
3799e5dd7070Spatrick return MSI;
3800e5dd7070Spatrick if (auto *FTSI = TemplateOrSpecialization
3801e5dd7070Spatrick .dyn_cast<FunctionTemplateSpecializationInfo *>())
3802e5dd7070Spatrick return FTSI->getMemberSpecializationInfo();
3803e5dd7070Spatrick return nullptr;
3804e5dd7070Spatrick }
3805e5dd7070Spatrick
3806e5dd7070Spatrick void
setInstantiationOfMemberFunction(ASTContext & C,FunctionDecl * FD,TemplateSpecializationKind TSK)3807e5dd7070Spatrick FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C,
3808e5dd7070Spatrick FunctionDecl *FD,
3809e5dd7070Spatrick TemplateSpecializationKind TSK) {
3810e5dd7070Spatrick assert(TemplateOrSpecialization.isNull() &&
3811e5dd7070Spatrick "Member function is already a specialization");
3812e5dd7070Spatrick MemberSpecializationInfo *Info
3813e5dd7070Spatrick = new (C) MemberSpecializationInfo(FD, TSK);
3814e5dd7070Spatrick TemplateOrSpecialization = Info;
3815e5dd7070Spatrick }
3816e5dd7070Spatrick
getDescribedFunctionTemplate() const3817e5dd7070Spatrick FunctionTemplateDecl *FunctionDecl::getDescribedFunctionTemplate() const {
3818*12c85518Srobert return dyn_cast_or_null<FunctionTemplateDecl>(
3819*12c85518Srobert TemplateOrSpecialization.dyn_cast<NamedDecl *>());
3820e5dd7070Spatrick }
3821e5dd7070Spatrick
setDescribedFunctionTemplate(FunctionTemplateDecl * Template)3822*12c85518Srobert void FunctionDecl::setDescribedFunctionTemplate(
3823*12c85518Srobert FunctionTemplateDecl *Template) {
3824e5dd7070Spatrick assert(TemplateOrSpecialization.isNull() &&
3825e5dd7070Spatrick "Member function is already a specialization");
3826e5dd7070Spatrick TemplateOrSpecialization = Template;
3827e5dd7070Spatrick }
3828e5dd7070Spatrick
setInstantiatedFromDecl(FunctionDecl * FD)3829*12c85518Srobert void FunctionDecl::setInstantiatedFromDecl(FunctionDecl *FD) {
3830*12c85518Srobert assert(TemplateOrSpecialization.isNull() &&
3831*12c85518Srobert "Function is already a specialization");
3832*12c85518Srobert TemplateOrSpecialization = FD;
3833*12c85518Srobert }
3834*12c85518Srobert
getInstantiatedFromDecl() const3835*12c85518Srobert FunctionDecl *FunctionDecl::getInstantiatedFromDecl() const {
3836*12c85518Srobert return dyn_cast_or_null<FunctionDecl>(
3837*12c85518Srobert TemplateOrSpecialization.dyn_cast<NamedDecl *>());
3838*12c85518Srobert }
3839*12c85518Srobert
isImplicitlyInstantiable() const3840e5dd7070Spatrick bool FunctionDecl::isImplicitlyInstantiable() const {
3841e5dd7070Spatrick // If the function is invalid, it can't be implicitly instantiated.
3842e5dd7070Spatrick if (isInvalidDecl())
3843e5dd7070Spatrick return false;
3844e5dd7070Spatrick
3845e5dd7070Spatrick switch (getTemplateSpecializationKindForInstantiation()) {
3846e5dd7070Spatrick case TSK_Undeclared:
3847e5dd7070Spatrick case TSK_ExplicitInstantiationDefinition:
3848e5dd7070Spatrick case TSK_ExplicitSpecialization:
3849e5dd7070Spatrick return false;
3850e5dd7070Spatrick
3851e5dd7070Spatrick case TSK_ImplicitInstantiation:
3852e5dd7070Spatrick return true;
3853e5dd7070Spatrick
3854e5dd7070Spatrick case TSK_ExplicitInstantiationDeclaration:
3855e5dd7070Spatrick // Handled below.
3856e5dd7070Spatrick break;
3857e5dd7070Spatrick }
3858e5dd7070Spatrick
3859e5dd7070Spatrick // Find the actual template from which we will instantiate.
3860e5dd7070Spatrick const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
3861e5dd7070Spatrick bool HasPattern = false;
3862e5dd7070Spatrick if (PatternDecl)
3863e5dd7070Spatrick HasPattern = PatternDecl->hasBody(PatternDecl);
3864e5dd7070Spatrick
3865e5dd7070Spatrick // C++0x [temp.explicit]p9:
3866e5dd7070Spatrick // Except for inline functions, other explicit instantiation declarations
3867e5dd7070Spatrick // have the effect of suppressing the implicit instantiation of the entity
3868e5dd7070Spatrick // to which they refer.
3869e5dd7070Spatrick if (!HasPattern || !PatternDecl)
3870e5dd7070Spatrick return true;
3871e5dd7070Spatrick
3872e5dd7070Spatrick return PatternDecl->isInlined();
3873e5dd7070Spatrick }
3874e5dd7070Spatrick
isTemplateInstantiation() const3875e5dd7070Spatrick bool FunctionDecl::isTemplateInstantiation() const {
3876e5dd7070Spatrick // FIXME: Remove this, it's not clear what it means. (Which template
3877e5dd7070Spatrick // specialization kind?)
3878e5dd7070Spatrick return clang::isTemplateInstantiation(getTemplateSpecializationKind());
3879e5dd7070Spatrick }
3880e5dd7070Spatrick
3881ec727ea7Spatrick FunctionDecl *
getTemplateInstantiationPattern(bool ForDefinition) const3882ec727ea7Spatrick FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const {
3883e5dd7070Spatrick // If this is a generic lambda call operator specialization, its
3884e5dd7070Spatrick // instantiation pattern is always its primary template's pattern
3885e5dd7070Spatrick // even if its primary template was instantiated from another
3886e5dd7070Spatrick // member template (which happens with nested generic lambdas).
3887e5dd7070Spatrick // Since a lambda's call operator's body is transformed eagerly,
3888e5dd7070Spatrick // we don't have to go hunting for a prototype definition template
3889e5dd7070Spatrick // (i.e. instantiated-from-member-template) to use as an instantiation
3890e5dd7070Spatrick // pattern.
3891e5dd7070Spatrick
3892e5dd7070Spatrick if (isGenericLambdaCallOperatorSpecialization(
3893e5dd7070Spatrick dyn_cast<CXXMethodDecl>(this))) {
3894e5dd7070Spatrick assert(getPrimaryTemplate() && "not a generic lambda call operator?");
3895e5dd7070Spatrick return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl());
3896e5dd7070Spatrick }
3897e5dd7070Spatrick
3898a9ac8606Spatrick // Check for a declaration of this function that was instantiated from a
3899a9ac8606Spatrick // friend definition.
3900a9ac8606Spatrick const FunctionDecl *FD = nullptr;
3901a9ac8606Spatrick if (!isDefined(FD, /*CheckForPendingFriendDefinition=*/true))
3902a9ac8606Spatrick FD = this;
3903a9ac8606Spatrick
3904a9ac8606Spatrick if (MemberSpecializationInfo *Info = FD->getMemberSpecializationInfo()) {
3905ec727ea7Spatrick if (ForDefinition &&
3906ec727ea7Spatrick !clang::isTemplateInstantiation(Info->getTemplateSpecializationKind()))
3907e5dd7070Spatrick return nullptr;
3908e5dd7070Spatrick return getDefinitionOrSelf(cast<FunctionDecl>(Info->getInstantiatedFrom()));
3909e5dd7070Spatrick }
3910e5dd7070Spatrick
3911ec727ea7Spatrick if (ForDefinition &&
3912ec727ea7Spatrick !clang::isTemplateInstantiation(getTemplateSpecializationKind()))
3913e5dd7070Spatrick return nullptr;
3914e5dd7070Spatrick
3915e5dd7070Spatrick if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
3916e5dd7070Spatrick // If we hit a point where the user provided a specialization of this
3917e5dd7070Spatrick // template, we're done looking.
3918ec727ea7Spatrick while (!ForDefinition || !Primary->isMemberSpecialization()) {
3919e5dd7070Spatrick auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate();
3920e5dd7070Spatrick if (!NewPrimary)
3921e5dd7070Spatrick break;
3922e5dd7070Spatrick Primary = NewPrimary;
3923e5dd7070Spatrick }
3924e5dd7070Spatrick
3925e5dd7070Spatrick return getDefinitionOrSelf(Primary->getTemplatedDecl());
3926e5dd7070Spatrick }
3927e5dd7070Spatrick
3928e5dd7070Spatrick return nullptr;
3929e5dd7070Spatrick }
3930e5dd7070Spatrick
getPrimaryTemplate() const3931e5dd7070Spatrick FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
3932e5dd7070Spatrick if (FunctionTemplateSpecializationInfo *Info
3933e5dd7070Spatrick = TemplateOrSpecialization
3934e5dd7070Spatrick .dyn_cast<FunctionTemplateSpecializationInfo*>()) {
3935e5dd7070Spatrick return Info->getTemplate();
3936e5dd7070Spatrick }
3937e5dd7070Spatrick return nullptr;
3938e5dd7070Spatrick }
3939e5dd7070Spatrick
3940e5dd7070Spatrick FunctionTemplateSpecializationInfo *
getTemplateSpecializationInfo() const3941e5dd7070Spatrick FunctionDecl::getTemplateSpecializationInfo() const {
3942e5dd7070Spatrick return TemplateOrSpecialization
3943e5dd7070Spatrick .dyn_cast<FunctionTemplateSpecializationInfo *>();
3944e5dd7070Spatrick }
3945e5dd7070Spatrick
3946e5dd7070Spatrick const TemplateArgumentList *
getTemplateSpecializationArgs() const3947e5dd7070Spatrick FunctionDecl::getTemplateSpecializationArgs() const {
3948e5dd7070Spatrick if (FunctionTemplateSpecializationInfo *Info
3949e5dd7070Spatrick = TemplateOrSpecialization
3950e5dd7070Spatrick .dyn_cast<FunctionTemplateSpecializationInfo*>()) {
3951e5dd7070Spatrick return Info->TemplateArguments;
3952e5dd7070Spatrick }
3953e5dd7070Spatrick return nullptr;
3954e5dd7070Spatrick }
3955e5dd7070Spatrick
3956e5dd7070Spatrick const ASTTemplateArgumentListInfo *
getTemplateSpecializationArgsAsWritten() const3957e5dd7070Spatrick FunctionDecl::getTemplateSpecializationArgsAsWritten() const {
3958e5dd7070Spatrick if (FunctionTemplateSpecializationInfo *Info
3959e5dd7070Spatrick = TemplateOrSpecialization
3960e5dd7070Spatrick .dyn_cast<FunctionTemplateSpecializationInfo*>()) {
3961e5dd7070Spatrick return Info->TemplateArgumentsAsWritten;
3962e5dd7070Spatrick }
3963e5dd7070Spatrick return nullptr;
3964e5dd7070Spatrick }
3965e5dd7070Spatrick
3966e5dd7070Spatrick void
setFunctionTemplateSpecialization(ASTContext & C,FunctionTemplateDecl * Template,const TemplateArgumentList * TemplateArgs,void * InsertPos,TemplateSpecializationKind TSK,const TemplateArgumentListInfo * TemplateArgsAsWritten,SourceLocation PointOfInstantiation)3967e5dd7070Spatrick FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
3968e5dd7070Spatrick FunctionTemplateDecl *Template,
3969e5dd7070Spatrick const TemplateArgumentList *TemplateArgs,
3970e5dd7070Spatrick void *InsertPos,
3971e5dd7070Spatrick TemplateSpecializationKind TSK,
3972e5dd7070Spatrick const TemplateArgumentListInfo *TemplateArgsAsWritten,
3973e5dd7070Spatrick SourceLocation PointOfInstantiation) {
3974e5dd7070Spatrick assert((TemplateOrSpecialization.isNull() ||
3975e5dd7070Spatrick TemplateOrSpecialization.is<MemberSpecializationInfo *>()) &&
3976e5dd7070Spatrick "Member function is already a specialization");
3977e5dd7070Spatrick assert(TSK != TSK_Undeclared &&
3978e5dd7070Spatrick "Must specify the type of function template specialization");
3979e5dd7070Spatrick assert((TemplateOrSpecialization.isNull() ||
3980e5dd7070Spatrick TSK == TSK_ExplicitSpecialization) &&
3981e5dd7070Spatrick "Member specialization must be an explicit specialization");
3982e5dd7070Spatrick FunctionTemplateSpecializationInfo *Info =
3983e5dd7070Spatrick FunctionTemplateSpecializationInfo::Create(
3984e5dd7070Spatrick C, this, Template, TSK, TemplateArgs, TemplateArgsAsWritten,
3985e5dd7070Spatrick PointOfInstantiation,
3986e5dd7070Spatrick TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>());
3987e5dd7070Spatrick TemplateOrSpecialization = Info;
3988e5dd7070Spatrick Template->addSpecialization(Info, InsertPos);
3989e5dd7070Spatrick }
3990e5dd7070Spatrick
3991e5dd7070Spatrick void
setDependentTemplateSpecialization(ASTContext & Context,const UnresolvedSetImpl & Templates,const TemplateArgumentListInfo & TemplateArgs)3992e5dd7070Spatrick FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context,
3993e5dd7070Spatrick const UnresolvedSetImpl &Templates,
3994e5dd7070Spatrick const TemplateArgumentListInfo &TemplateArgs) {
3995e5dd7070Spatrick assert(TemplateOrSpecialization.isNull());
3996e5dd7070Spatrick DependentFunctionTemplateSpecializationInfo *Info =
3997e5dd7070Spatrick DependentFunctionTemplateSpecializationInfo::Create(Context, Templates,
3998e5dd7070Spatrick TemplateArgs);
3999e5dd7070Spatrick TemplateOrSpecialization = Info;
4000e5dd7070Spatrick }
4001e5dd7070Spatrick
4002e5dd7070Spatrick DependentFunctionTemplateSpecializationInfo *
getDependentSpecializationInfo() const4003e5dd7070Spatrick FunctionDecl::getDependentSpecializationInfo() const {
4004e5dd7070Spatrick return TemplateOrSpecialization
4005e5dd7070Spatrick .dyn_cast<DependentFunctionTemplateSpecializationInfo *>();
4006e5dd7070Spatrick }
4007e5dd7070Spatrick
4008e5dd7070Spatrick DependentFunctionTemplateSpecializationInfo *
Create(ASTContext & Context,const UnresolvedSetImpl & Ts,const TemplateArgumentListInfo & TArgs)4009e5dd7070Spatrick DependentFunctionTemplateSpecializationInfo::Create(
4010e5dd7070Spatrick ASTContext &Context, const UnresolvedSetImpl &Ts,
4011e5dd7070Spatrick const TemplateArgumentListInfo &TArgs) {
4012e5dd7070Spatrick void *Buffer = Context.Allocate(
4013e5dd7070Spatrick totalSizeToAlloc<TemplateArgumentLoc, FunctionTemplateDecl *>(
4014e5dd7070Spatrick TArgs.size(), Ts.size()));
4015e5dd7070Spatrick return new (Buffer) DependentFunctionTemplateSpecializationInfo(Ts, TArgs);
4016e5dd7070Spatrick }
4017e5dd7070Spatrick
4018e5dd7070Spatrick DependentFunctionTemplateSpecializationInfo::
DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl & Ts,const TemplateArgumentListInfo & TArgs)4019e5dd7070Spatrick DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts,
4020e5dd7070Spatrick const TemplateArgumentListInfo &TArgs)
4021e5dd7070Spatrick : AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) {
4022e5dd7070Spatrick NumTemplates = Ts.size();
4023e5dd7070Spatrick NumArgs = TArgs.size();
4024e5dd7070Spatrick
4025e5dd7070Spatrick FunctionTemplateDecl **TsArray = getTrailingObjects<FunctionTemplateDecl *>();
4026e5dd7070Spatrick for (unsigned I = 0, E = Ts.size(); I != E; ++I)
4027e5dd7070Spatrick TsArray[I] = cast<FunctionTemplateDecl>(Ts[I]->getUnderlyingDecl());
4028e5dd7070Spatrick
4029e5dd7070Spatrick TemplateArgumentLoc *ArgsArray = getTrailingObjects<TemplateArgumentLoc>();
4030e5dd7070Spatrick for (unsigned I = 0, E = TArgs.size(); I != E; ++I)
4031e5dd7070Spatrick new (&ArgsArray[I]) TemplateArgumentLoc(TArgs[I]);
4032e5dd7070Spatrick }
4033e5dd7070Spatrick
getTemplateSpecializationKind() const4034e5dd7070Spatrick TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
4035e5dd7070Spatrick // For a function template specialization, query the specialization
4036e5dd7070Spatrick // information object.
4037e5dd7070Spatrick if (FunctionTemplateSpecializationInfo *FTSInfo =
4038e5dd7070Spatrick TemplateOrSpecialization
4039e5dd7070Spatrick .dyn_cast<FunctionTemplateSpecializationInfo *>())
4040e5dd7070Spatrick return FTSInfo->getTemplateSpecializationKind();
4041e5dd7070Spatrick
4042e5dd7070Spatrick if (MemberSpecializationInfo *MSInfo =
4043e5dd7070Spatrick TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
4044e5dd7070Spatrick return MSInfo->getTemplateSpecializationKind();
4045e5dd7070Spatrick
4046e5dd7070Spatrick return TSK_Undeclared;
4047e5dd7070Spatrick }
4048e5dd7070Spatrick
4049e5dd7070Spatrick TemplateSpecializationKind
getTemplateSpecializationKindForInstantiation() const4050e5dd7070Spatrick FunctionDecl::getTemplateSpecializationKindForInstantiation() const {
4051e5dd7070Spatrick // This is the same as getTemplateSpecializationKind(), except that for a
4052e5dd7070Spatrick // function that is both a function template specialization and a member
4053e5dd7070Spatrick // specialization, we prefer the member specialization information. Eg:
4054e5dd7070Spatrick //
4055e5dd7070Spatrick // template<typename T> struct A {
4056e5dd7070Spatrick // template<typename U> void f() {}
4057e5dd7070Spatrick // template<> void f<int>() {}
4058e5dd7070Spatrick // };
4059e5dd7070Spatrick //
4060e5dd7070Spatrick // For A<int>::f<int>():
4061e5dd7070Spatrick // * getTemplateSpecializationKind() will return TSK_ExplicitSpecialization
4062e5dd7070Spatrick // * getTemplateSpecializationKindForInstantiation() will return
4063e5dd7070Spatrick // TSK_ImplicitInstantiation
4064e5dd7070Spatrick //
4065e5dd7070Spatrick // This reflects the facts that A<int>::f<int> is an explicit specialization
4066e5dd7070Spatrick // of A<int>::f, and that A<int>::f<int> should be implicitly instantiated
4067e5dd7070Spatrick // from A::f<int> if a definition is needed.
4068e5dd7070Spatrick if (FunctionTemplateSpecializationInfo *FTSInfo =
4069e5dd7070Spatrick TemplateOrSpecialization
4070e5dd7070Spatrick .dyn_cast<FunctionTemplateSpecializationInfo *>()) {
4071e5dd7070Spatrick if (auto *MSInfo = FTSInfo->getMemberSpecializationInfo())
4072e5dd7070Spatrick return MSInfo->getTemplateSpecializationKind();
4073e5dd7070Spatrick return FTSInfo->getTemplateSpecializationKind();
4074e5dd7070Spatrick }
4075e5dd7070Spatrick
4076e5dd7070Spatrick if (MemberSpecializationInfo *MSInfo =
4077e5dd7070Spatrick TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
4078e5dd7070Spatrick return MSInfo->getTemplateSpecializationKind();
4079e5dd7070Spatrick
4080e5dd7070Spatrick return TSK_Undeclared;
4081e5dd7070Spatrick }
4082e5dd7070Spatrick
4083e5dd7070Spatrick void
setTemplateSpecializationKind(TemplateSpecializationKind TSK,SourceLocation PointOfInstantiation)4084e5dd7070Spatrick FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
4085e5dd7070Spatrick SourceLocation PointOfInstantiation) {
4086e5dd7070Spatrick if (FunctionTemplateSpecializationInfo *FTSInfo
4087e5dd7070Spatrick = TemplateOrSpecialization.dyn_cast<
4088e5dd7070Spatrick FunctionTemplateSpecializationInfo*>()) {
4089e5dd7070Spatrick FTSInfo->setTemplateSpecializationKind(TSK);
4090e5dd7070Spatrick if (TSK != TSK_ExplicitSpecialization &&
4091e5dd7070Spatrick PointOfInstantiation.isValid() &&
4092e5dd7070Spatrick FTSInfo->getPointOfInstantiation().isInvalid()) {
4093e5dd7070Spatrick FTSInfo->setPointOfInstantiation(PointOfInstantiation);
4094e5dd7070Spatrick if (ASTMutationListener *L = getASTContext().getASTMutationListener())
4095e5dd7070Spatrick L->InstantiationRequested(this);
4096e5dd7070Spatrick }
4097e5dd7070Spatrick } else if (MemberSpecializationInfo *MSInfo
4098e5dd7070Spatrick = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) {
4099e5dd7070Spatrick MSInfo->setTemplateSpecializationKind(TSK);
4100e5dd7070Spatrick if (TSK != TSK_ExplicitSpecialization &&
4101e5dd7070Spatrick PointOfInstantiation.isValid() &&
4102e5dd7070Spatrick MSInfo->getPointOfInstantiation().isInvalid()) {
4103e5dd7070Spatrick MSInfo->setPointOfInstantiation(PointOfInstantiation);
4104e5dd7070Spatrick if (ASTMutationListener *L = getASTContext().getASTMutationListener())
4105e5dd7070Spatrick L->InstantiationRequested(this);
4106e5dd7070Spatrick }
4107e5dd7070Spatrick } else
4108e5dd7070Spatrick llvm_unreachable("Function cannot have a template specialization kind");
4109e5dd7070Spatrick }
4110e5dd7070Spatrick
getPointOfInstantiation() const4111e5dd7070Spatrick SourceLocation FunctionDecl::getPointOfInstantiation() const {
4112e5dd7070Spatrick if (FunctionTemplateSpecializationInfo *FTSInfo
4113e5dd7070Spatrick = TemplateOrSpecialization.dyn_cast<
4114e5dd7070Spatrick FunctionTemplateSpecializationInfo*>())
4115e5dd7070Spatrick return FTSInfo->getPointOfInstantiation();
4116a9ac8606Spatrick if (MemberSpecializationInfo *MSInfo =
4117a9ac8606Spatrick TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
4118e5dd7070Spatrick return MSInfo->getPointOfInstantiation();
4119e5dd7070Spatrick
4120e5dd7070Spatrick return SourceLocation();
4121e5dd7070Spatrick }
4122e5dd7070Spatrick
isOutOfLine() const4123e5dd7070Spatrick bool FunctionDecl::isOutOfLine() const {
4124e5dd7070Spatrick if (Decl::isOutOfLine())
4125e5dd7070Spatrick return true;
4126e5dd7070Spatrick
4127e5dd7070Spatrick // If this function was instantiated from a member function of a
4128e5dd7070Spatrick // class template, check whether that member function was defined out-of-line.
4129e5dd7070Spatrick if (FunctionDecl *FD = getInstantiatedFromMemberFunction()) {
4130e5dd7070Spatrick const FunctionDecl *Definition;
4131e5dd7070Spatrick if (FD->hasBody(Definition))
4132e5dd7070Spatrick return Definition->isOutOfLine();
4133e5dd7070Spatrick }
4134e5dd7070Spatrick
4135e5dd7070Spatrick // If this function was instantiated from a function template,
4136e5dd7070Spatrick // check whether that function template was defined out-of-line.
4137e5dd7070Spatrick if (FunctionTemplateDecl *FunTmpl = getPrimaryTemplate()) {
4138e5dd7070Spatrick const FunctionDecl *Definition;
4139e5dd7070Spatrick if (FunTmpl->getTemplatedDecl()->hasBody(Definition))
4140e5dd7070Spatrick return Definition->isOutOfLine();
4141e5dd7070Spatrick }
4142e5dd7070Spatrick
4143e5dd7070Spatrick return false;
4144e5dd7070Spatrick }
4145e5dd7070Spatrick
getSourceRange() const4146e5dd7070Spatrick SourceRange FunctionDecl::getSourceRange() const {
4147e5dd7070Spatrick return SourceRange(getOuterLocStart(), EndRangeLoc);
4148e5dd7070Spatrick }
4149e5dd7070Spatrick
getMemoryFunctionKind() const4150e5dd7070Spatrick unsigned FunctionDecl::getMemoryFunctionKind() const {
4151e5dd7070Spatrick IdentifierInfo *FnInfo = getIdentifier();
4152e5dd7070Spatrick
4153e5dd7070Spatrick if (!FnInfo)
4154e5dd7070Spatrick return 0;
4155e5dd7070Spatrick
4156e5dd7070Spatrick // Builtin handling.
4157e5dd7070Spatrick switch (getBuiltinID()) {
4158e5dd7070Spatrick case Builtin::BI__builtin_memset:
4159e5dd7070Spatrick case Builtin::BI__builtin___memset_chk:
4160e5dd7070Spatrick case Builtin::BImemset:
4161e5dd7070Spatrick return Builtin::BImemset;
4162e5dd7070Spatrick
4163e5dd7070Spatrick case Builtin::BI__builtin_memcpy:
4164e5dd7070Spatrick case Builtin::BI__builtin___memcpy_chk:
4165e5dd7070Spatrick case Builtin::BImemcpy:
4166e5dd7070Spatrick return Builtin::BImemcpy;
4167e5dd7070Spatrick
4168e5dd7070Spatrick case Builtin::BI__builtin_mempcpy:
4169e5dd7070Spatrick case Builtin::BI__builtin___mempcpy_chk:
4170e5dd7070Spatrick case Builtin::BImempcpy:
4171e5dd7070Spatrick return Builtin::BImempcpy;
4172e5dd7070Spatrick
4173e5dd7070Spatrick case Builtin::BI__builtin_memmove:
4174e5dd7070Spatrick case Builtin::BI__builtin___memmove_chk:
4175e5dd7070Spatrick case Builtin::BImemmove:
4176e5dd7070Spatrick return Builtin::BImemmove;
4177e5dd7070Spatrick
4178e5dd7070Spatrick case Builtin::BIstrlcpy:
4179e5dd7070Spatrick case Builtin::BI__builtin___strlcpy_chk:
4180e5dd7070Spatrick return Builtin::BIstrlcpy;
4181e5dd7070Spatrick
4182e5dd7070Spatrick case Builtin::BIstrlcat:
4183e5dd7070Spatrick case Builtin::BI__builtin___strlcat_chk:
4184e5dd7070Spatrick return Builtin::BIstrlcat;
4185e5dd7070Spatrick
4186e5dd7070Spatrick case Builtin::BI__builtin_memcmp:
4187e5dd7070Spatrick case Builtin::BImemcmp:
4188e5dd7070Spatrick return Builtin::BImemcmp;
4189e5dd7070Spatrick
4190e5dd7070Spatrick case Builtin::BI__builtin_bcmp:
4191e5dd7070Spatrick case Builtin::BIbcmp:
4192e5dd7070Spatrick return Builtin::BIbcmp;
4193e5dd7070Spatrick
4194e5dd7070Spatrick case Builtin::BI__builtin_strncpy:
4195e5dd7070Spatrick case Builtin::BI__builtin___strncpy_chk:
4196e5dd7070Spatrick case Builtin::BIstrncpy:
4197e5dd7070Spatrick return Builtin::BIstrncpy;
4198e5dd7070Spatrick
4199e5dd7070Spatrick case Builtin::BI__builtin_strncmp:
4200e5dd7070Spatrick case Builtin::BIstrncmp:
4201e5dd7070Spatrick return Builtin::BIstrncmp;
4202e5dd7070Spatrick
4203e5dd7070Spatrick case Builtin::BI__builtin_strncasecmp:
4204e5dd7070Spatrick case Builtin::BIstrncasecmp:
4205e5dd7070Spatrick return Builtin::BIstrncasecmp;
4206e5dd7070Spatrick
4207e5dd7070Spatrick case Builtin::BI__builtin_strncat:
4208e5dd7070Spatrick case Builtin::BI__builtin___strncat_chk:
4209e5dd7070Spatrick case Builtin::BIstrncat:
4210e5dd7070Spatrick return Builtin::BIstrncat;
4211e5dd7070Spatrick
4212e5dd7070Spatrick case Builtin::BI__builtin_strndup:
4213e5dd7070Spatrick case Builtin::BIstrndup:
4214e5dd7070Spatrick return Builtin::BIstrndup;
4215e5dd7070Spatrick
4216e5dd7070Spatrick case Builtin::BI__builtin_strlen:
4217e5dd7070Spatrick case Builtin::BIstrlen:
4218e5dd7070Spatrick return Builtin::BIstrlen;
4219e5dd7070Spatrick
4220e5dd7070Spatrick case Builtin::BI__builtin_bzero:
4221e5dd7070Spatrick case Builtin::BIbzero:
4222e5dd7070Spatrick return Builtin::BIbzero;
4223e5dd7070Spatrick
4224a9ac8606Spatrick case Builtin::BIfree:
4225a9ac8606Spatrick return Builtin::BIfree;
4226a9ac8606Spatrick
4227e5dd7070Spatrick default:
4228e5dd7070Spatrick if (isExternC()) {
4229e5dd7070Spatrick if (FnInfo->isStr("memset"))
4230e5dd7070Spatrick return Builtin::BImemset;
4231a9ac8606Spatrick if (FnInfo->isStr("memcpy"))
4232e5dd7070Spatrick return Builtin::BImemcpy;
4233a9ac8606Spatrick if (FnInfo->isStr("mempcpy"))
4234e5dd7070Spatrick return Builtin::BImempcpy;
4235a9ac8606Spatrick if (FnInfo->isStr("memmove"))
4236e5dd7070Spatrick return Builtin::BImemmove;
4237a9ac8606Spatrick if (FnInfo->isStr("memcmp"))
4238e5dd7070Spatrick return Builtin::BImemcmp;
4239a9ac8606Spatrick if (FnInfo->isStr("bcmp"))
4240e5dd7070Spatrick return Builtin::BIbcmp;
4241a9ac8606Spatrick if (FnInfo->isStr("strncpy"))
4242e5dd7070Spatrick return Builtin::BIstrncpy;
4243a9ac8606Spatrick if (FnInfo->isStr("strncmp"))
4244e5dd7070Spatrick return Builtin::BIstrncmp;
4245a9ac8606Spatrick if (FnInfo->isStr("strncasecmp"))
4246e5dd7070Spatrick return Builtin::BIstrncasecmp;
4247a9ac8606Spatrick if (FnInfo->isStr("strncat"))
4248e5dd7070Spatrick return Builtin::BIstrncat;
4249a9ac8606Spatrick if (FnInfo->isStr("strndup"))
4250e5dd7070Spatrick return Builtin::BIstrndup;
4251a9ac8606Spatrick if (FnInfo->isStr("strlen"))
4252e5dd7070Spatrick return Builtin::BIstrlen;
4253a9ac8606Spatrick if (FnInfo->isStr("bzero"))
4254e5dd7070Spatrick return Builtin::BIbzero;
4255a9ac8606Spatrick } else if (isInStdNamespace()) {
4256a9ac8606Spatrick if (FnInfo->isStr("free"))
4257a9ac8606Spatrick return Builtin::BIfree;
4258e5dd7070Spatrick }
4259e5dd7070Spatrick break;
4260e5dd7070Spatrick }
4261e5dd7070Spatrick return 0;
4262e5dd7070Spatrick }
4263e5dd7070Spatrick
getODRHash() const4264e5dd7070Spatrick unsigned FunctionDecl::getODRHash() const {
4265e5dd7070Spatrick assert(hasODRHash());
4266e5dd7070Spatrick return ODRHash;
4267e5dd7070Spatrick }
4268e5dd7070Spatrick
getODRHash()4269e5dd7070Spatrick unsigned FunctionDecl::getODRHash() {
4270e5dd7070Spatrick if (hasODRHash())
4271e5dd7070Spatrick return ODRHash;
4272e5dd7070Spatrick
4273e5dd7070Spatrick if (auto *FT = getInstantiatedFromMemberFunction()) {
4274e5dd7070Spatrick setHasODRHash(true);
4275e5dd7070Spatrick ODRHash = FT->getODRHash();
4276e5dd7070Spatrick return ODRHash;
4277e5dd7070Spatrick }
4278e5dd7070Spatrick
4279e5dd7070Spatrick class ODRHash Hash;
4280e5dd7070Spatrick Hash.AddFunctionDecl(this);
4281e5dd7070Spatrick setHasODRHash(true);
4282e5dd7070Spatrick ODRHash = Hash.CalculateHash();
4283e5dd7070Spatrick return ODRHash;
4284e5dd7070Spatrick }
4285e5dd7070Spatrick
4286e5dd7070Spatrick //===----------------------------------------------------------------------===//
4287e5dd7070Spatrick // FieldDecl Implementation
4288e5dd7070Spatrick //===----------------------------------------------------------------------===//
4289e5dd7070Spatrick
Create(const ASTContext & C,DeclContext * DC,SourceLocation StartLoc,SourceLocation IdLoc,IdentifierInfo * Id,QualType T,TypeSourceInfo * TInfo,Expr * BW,bool Mutable,InClassInitStyle InitStyle)4290e5dd7070Spatrick FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC,
4291e5dd7070Spatrick SourceLocation StartLoc, SourceLocation IdLoc,
4292e5dd7070Spatrick IdentifierInfo *Id, QualType T,
4293e5dd7070Spatrick TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
4294e5dd7070Spatrick InClassInitStyle InitStyle) {
4295e5dd7070Spatrick return new (C, DC) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo,
4296e5dd7070Spatrick BW, Mutable, InitStyle);
4297e5dd7070Spatrick }
4298e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID)4299e5dd7070Spatrick FieldDecl *FieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
4300e5dd7070Spatrick return new (C, ID) FieldDecl(Field, nullptr, SourceLocation(),
4301e5dd7070Spatrick SourceLocation(), nullptr, QualType(), nullptr,
4302e5dd7070Spatrick nullptr, false, ICIS_NoInit);
4303e5dd7070Spatrick }
4304e5dd7070Spatrick
isAnonymousStructOrUnion() const4305e5dd7070Spatrick bool FieldDecl::isAnonymousStructOrUnion() const {
4306e5dd7070Spatrick if (!isImplicit() || getDeclName())
4307e5dd7070Spatrick return false;
4308e5dd7070Spatrick
4309e5dd7070Spatrick if (const auto *Record = getType()->getAs<RecordType>())
4310e5dd7070Spatrick return Record->getDecl()->isAnonymousStructOrUnion();
4311e5dd7070Spatrick
4312e5dd7070Spatrick return false;
4313e5dd7070Spatrick }
4314e5dd7070Spatrick
getBitWidthValue(const ASTContext & Ctx) const4315e5dd7070Spatrick unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
4316e5dd7070Spatrick assert(isBitField() && "not a bitfield");
4317e5dd7070Spatrick return getBitWidth()->EvaluateKnownConstInt(Ctx).getZExtValue();
4318e5dd7070Spatrick }
4319e5dd7070Spatrick
isZeroLengthBitField(const ASTContext & Ctx) const4320e5dd7070Spatrick bool FieldDecl::isZeroLengthBitField(const ASTContext &Ctx) const {
4321e5dd7070Spatrick return isUnnamedBitfield() && !getBitWidth()->isValueDependent() &&
4322e5dd7070Spatrick getBitWidthValue(Ctx) == 0;
4323e5dd7070Spatrick }
4324e5dd7070Spatrick
isZeroSize(const ASTContext & Ctx) const4325e5dd7070Spatrick bool FieldDecl::isZeroSize(const ASTContext &Ctx) const {
4326e5dd7070Spatrick if (isZeroLengthBitField(Ctx))
4327e5dd7070Spatrick return true;
4328e5dd7070Spatrick
4329e5dd7070Spatrick // C++2a [intro.object]p7:
4330e5dd7070Spatrick // An object has nonzero size if it
4331e5dd7070Spatrick // -- is not a potentially-overlapping subobject, or
4332e5dd7070Spatrick if (!hasAttr<NoUniqueAddressAttr>())
4333e5dd7070Spatrick return false;
4334e5dd7070Spatrick
4335e5dd7070Spatrick // -- is not of class type, or
4336e5dd7070Spatrick const auto *RT = getType()->getAs<RecordType>();
4337e5dd7070Spatrick if (!RT)
4338e5dd7070Spatrick return false;
4339e5dd7070Spatrick const RecordDecl *RD = RT->getDecl()->getDefinition();
4340e5dd7070Spatrick if (!RD) {
4341e5dd7070Spatrick assert(isInvalidDecl() && "valid field has incomplete type");
4342e5dd7070Spatrick return false;
4343e5dd7070Spatrick }
4344e5dd7070Spatrick
4345e5dd7070Spatrick // -- [has] virtual member functions or virtual base classes, or
4346e5dd7070Spatrick // -- has subobjects of nonzero size or bit-fields of nonzero length
4347e5dd7070Spatrick const auto *CXXRD = cast<CXXRecordDecl>(RD);
4348e5dd7070Spatrick if (!CXXRD->isEmpty())
4349e5dd7070Spatrick return false;
4350e5dd7070Spatrick
4351e5dd7070Spatrick // Otherwise, [...] the circumstances under which the object has zero size
4352e5dd7070Spatrick // are implementation-defined.
4353e5dd7070Spatrick // FIXME: This might be Itanium ABI specific; we don't yet know what the MS
4354e5dd7070Spatrick // ABI will do.
4355e5dd7070Spatrick return true;
4356e5dd7070Spatrick }
4357e5dd7070Spatrick
getFieldIndex() const4358e5dd7070Spatrick unsigned FieldDecl::getFieldIndex() const {
4359e5dd7070Spatrick const FieldDecl *Canonical = getCanonicalDecl();
4360e5dd7070Spatrick if (Canonical != this)
4361e5dd7070Spatrick return Canonical->getFieldIndex();
4362e5dd7070Spatrick
4363e5dd7070Spatrick if (CachedFieldIndex) return CachedFieldIndex - 1;
4364e5dd7070Spatrick
4365e5dd7070Spatrick unsigned Index = 0;
4366e5dd7070Spatrick const RecordDecl *RD = getParent()->getDefinition();
4367e5dd7070Spatrick assert(RD && "requested index for field of struct with no definition");
4368e5dd7070Spatrick
4369e5dd7070Spatrick for (auto *Field : RD->fields()) {
4370e5dd7070Spatrick Field->getCanonicalDecl()->CachedFieldIndex = Index + 1;
4371e5dd7070Spatrick ++Index;
4372e5dd7070Spatrick }
4373e5dd7070Spatrick
4374e5dd7070Spatrick assert(CachedFieldIndex && "failed to find field in parent");
4375e5dd7070Spatrick return CachedFieldIndex - 1;
4376e5dd7070Spatrick }
4377e5dd7070Spatrick
getSourceRange() const4378e5dd7070Spatrick SourceRange FieldDecl::getSourceRange() const {
4379e5dd7070Spatrick const Expr *FinalExpr = getInClassInitializer();
4380e5dd7070Spatrick if (!FinalExpr)
4381e5dd7070Spatrick FinalExpr = getBitWidth();
4382e5dd7070Spatrick if (FinalExpr)
4383e5dd7070Spatrick return SourceRange(getInnerLocStart(), FinalExpr->getEndLoc());
4384e5dd7070Spatrick return DeclaratorDecl::getSourceRange();
4385e5dd7070Spatrick }
4386e5dd7070Spatrick
setCapturedVLAType(const VariableArrayType * VLAType)4387e5dd7070Spatrick void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) {
4388e5dd7070Spatrick assert((getParent()->isLambda() || getParent()->isCapturedRecord()) &&
4389e5dd7070Spatrick "capturing type in non-lambda or captured record.");
4390e5dd7070Spatrick assert(InitStorage.getInt() == ISK_NoInit &&
4391e5dd7070Spatrick InitStorage.getPointer() == nullptr &&
4392e5dd7070Spatrick "bit width, initializer or captured type already set");
4393e5dd7070Spatrick InitStorage.setPointerAndInt(const_cast<VariableArrayType *>(VLAType),
4394e5dd7070Spatrick ISK_CapturedVLAType);
4395e5dd7070Spatrick }
4396e5dd7070Spatrick
4397e5dd7070Spatrick //===----------------------------------------------------------------------===//
4398e5dd7070Spatrick // TagDecl Implementation
4399e5dd7070Spatrick //===----------------------------------------------------------------------===//
4400e5dd7070Spatrick
TagDecl(Kind DK,TagKind TK,const ASTContext & C,DeclContext * DC,SourceLocation L,IdentifierInfo * Id,TagDecl * PrevDecl,SourceLocation StartL)4401e5dd7070Spatrick TagDecl::TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
4402e5dd7070Spatrick SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl,
4403e5dd7070Spatrick SourceLocation StartL)
4404e5dd7070Spatrick : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), redeclarable_base(C),
4405e5dd7070Spatrick TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) {
4406e5dd7070Spatrick assert((DK != Enum || TK == TTK_Enum) &&
4407e5dd7070Spatrick "EnumDecl not matched with TTK_Enum");
4408e5dd7070Spatrick setPreviousDecl(PrevDecl);
4409e5dd7070Spatrick setTagKind(TK);
4410e5dd7070Spatrick setCompleteDefinition(false);
4411e5dd7070Spatrick setBeingDefined(false);
4412e5dd7070Spatrick setEmbeddedInDeclarator(false);
4413e5dd7070Spatrick setFreeStanding(false);
4414e5dd7070Spatrick setCompleteDefinitionRequired(false);
4415*12c85518Srobert TagDeclBits.IsThisDeclarationADemotedDefinition = false;
4416e5dd7070Spatrick }
4417e5dd7070Spatrick
getOuterLocStart() const4418e5dd7070Spatrick SourceLocation TagDecl::getOuterLocStart() const {
4419e5dd7070Spatrick return getTemplateOrInnerLocStart(this);
4420e5dd7070Spatrick }
4421e5dd7070Spatrick
getSourceRange() const4422e5dd7070Spatrick SourceRange TagDecl::getSourceRange() const {
4423e5dd7070Spatrick SourceLocation RBraceLoc = BraceRange.getEnd();
4424e5dd7070Spatrick SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation();
4425e5dd7070Spatrick return SourceRange(getOuterLocStart(), E);
4426e5dd7070Spatrick }
4427e5dd7070Spatrick
getCanonicalDecl()4428e5dd7070Spatrick TagDecl *TagDecl::getCanonicalDecl() { return getFirstDecl(); }
4429e5dd7070Spatrick
setTypedefNameForAnonDecl(TypedefNameDecl * TDD)4430e5dd7070Spatrick void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) {
4431e5dd7070Spatrick TypedefNameDeclOrQualifier = TDD;
4432e5dd7070Spatrick if (const Type *T = getTypeForDecl()) {
4433e5dd7070Spatrick (void)T;
4434e5dd7070Spatrick assert(T->isLinkageValid());
4435e5dd7070Spatrick }
4436e5dd7070Spatrick assert(isLinkageValid());
4437e5dd7070Spatrick }
4438e5dd7070Spatrick
startDefinition()4439e5dd7070Spatrick void TagDecl::startDefinition() {
4440e5dd7070Spatrick setBeingDefined(true);
4441e5dd7070Spatrick
4442e5dd7070Spatrick if (auto *D = dyn_cast<CXXRecordDecl>(this)) {
4443e5dd7070Spatrick struct CXXRecordDecl::DefinitionData *Data =
4444e5dd7070Spatrick new (getASTContext()) struct CXXRecordDecl::DefinitionData(D);
4445*12c85518Srobert for (auto *I : redecls())
4446e5dd7070Spatrick cast<CXXRecordDecl>(I)->DefinitionData = Data;
4447e5dd7070Spatrick }
4448e5dd7070Spatrick }
4449e5dd7070Spatrick
completeDefinition()4450e5dd7070Spatrick void TagDecl::completeDefinition() {
4451e5dd7070Spatrick assert((!isa<CXXRecordDecl>(this) ||
4452e5dd7070Spatrick cast<CXXRecordDecl>(this)->hasDefinition()) &&
4453e5dd7070Spatrick "definition completed but not started");
4454e5dd7070Spatrick
4455e5dd7070Spatrick setCompleteDefinition(true);
4456e5dd7070Spatrick setBeingDefined(false);
4457e5dd7070Spatrick
4458e5dd7070Spatrick if (ASTMutationListener *L = getASTMutationListener())
4459e5dd7070Spatrick L->CompletedTagDefinition(this);
4460e5dd7070Spatrick }
4461e5dd7070Spatrick
getDefinition() const4462e5dd7070Spatrick TagDecl *TagDecl::getDefinition() const {
4463e5dd7070Spatrick if (isCompleteDefinition())
4464e5dd7070Spatrick return const_cast<TagDecl *>(this);
4465e5dd7070Spatrick
4466e5dd7070Spatrick // If it's possible for us to have an out-of-date definition, check now.
4467e5dd7070Spatrick if (mayHaveOutOfDateDef()) {
4468e5dd7070Spatrick if (IdentifierInfo *II = getIdentifier()) {
4469e5dd7070Spatrick if (II->isOutOfDate()) {
4470e5dd7070Spatrick updateOutOfDate(*II);
4471e5dd7070Spatrick }
4472e5dd7070Spatrick }
4473e5dd7070Spatrick }
4474e5dd7070Spatrick
4475e5dd7070Spatrick if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(this))
4476e5dd7070Spatrick return CXXRD->getDefinition();
4477e5dd7070Spatrick
4478*12c85518Srobert for (auto *R : redecls())
4479e5dd7070Spatrick if (R->isCompleteDefinition())
4480e5dd7070Spatrick return R;
4481e5dd7070Spatrick
4482e5dd7070Spatrick return nullptr;
4483e5dd7070Spatrick }
4484e5dd7070Spatrick
setQualifierInfo(NestedNameSpecifierLoc QualifierLoc)4485e5dd7070Spatrick void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
4486e5dd7070Spatrick if (QualifierLoc) {
4487e5dd7070Spatrick // Make sure the extended qualifier info is allocated.
4488e5dd7070Spatrick if (!hasExtInfo())
4489e5dd7070Spatrick TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo;
4490e5dd7070Spatrick // Set qualifier info.
4491e5dd7070Spatrick getExtInfo()->QualifierLoc = QualifierLoc;
4492e5dd7070Spatrick } else {
4493e5dd7070Spatrick // Here Qualifier == 0, i.e., we are removing the qualifier (if any).
4494e5dd7070Spatrick if (hasExtInfo()) {
4495e5dd7070Spatrick if (getExtInfo()->NumTemplParamLists == 0) {
4496e5dd7070Spatrick getASTContext().Deallocate(getExtInfo());
4497e5dd7070Spatrick TypedefNameDeclOrQualifier = (TypedefNameDecl *)nullptr;
4498e5dd7070Spatrick }
4499e5dd7070Spatrick else
4500e5dd7070Spatrick getExtInfo()->QualifierLoc = QualifierLoc;
4501e5dd7070Spatrick }
4502e5dd7070Spatrick }
4503e5dd7070Spatrick }
4504e5dd7070Spatrick
printName(raw_ostream & OS,const PrintingPolicy & Policy) const4505*12c85518Srobert void TagDecl::printName(raw_ostream &OS, const PrintingPolicy &Policy) const {
4506*12c85518Srobert DeclarationName Name = getDeclName();
4507*12c85518Srobert // If the name is supposed to have an identifier but does not have one, then
4508*12c85518Srobert // the tag is anonymous and we should print it differently.
4509*12c85518Srobert if (Name.isIdentifier() && !Name.getAsIdentifierInfo()) {
4510*12c85518Srobert // If the caller wanted to print a qualified name, they've already printed
4511*12c85518Srobert // the scope. And if the caller doesn't want that, the scope information
4512*12c85518Srobert // is already printed as part of the type.
4513*12c85518Srobert PrintingPolicy Copy(Policy);
4514*12c85518Srobert Copy.SuppressScope = true;
4515*12c85518Srobert getASTContext().getTagDeclType(this).print(OS, Copy);
4516*12c85518Srobert return;
4517*12c85518Srobert }
4518*12c85518Srobert // Otherwise, do the normal printing.
4519*12c85518Srobert Name.print(OS, Policy);
4520*12c85518Srobert }
4521*12c85518Srobert
setTemplateParameterListsInfo(ASTContext & Context,ArrayRef<TemplateParameterList * > TPLists)4522e5dd7070Spatrick void TagDecl::setTemplateParameterListsInfo(
4523e5dd7070Spatrick ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
4524e5dd7070Spatrick assert(!TPLists.empty());
4525e5dd7070Spatrick // Make sure the extended decl info is allocated.
4526e5dd7070Spatrick if (!hasExtInfo())
4527e5dd7070Spatrick // Allocate external info struct.
4528e5dd7070Spatrick TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo;
4529e5dd7070Spatrick // Set the template parameter lists info.
4530e5dd7070Spatrick getExtInfo()->setTemplateParameterListsInfo(Context, TPLists);
4531e5dd7070Spatrick }
4532e5dd7070Spatrick
4533e5dd7070Spatrick //===----------------------------------------------------------------------===//
4534e5dd7070Spatrick // EnumDecl Implementation
4535e5dd7070Spatrick //===----------------------------------------------------------------------===//
4536e5dd7070Spatrick
EnumDecl(ASTContext & C,DeclContext * DC,SourceLocation StartLoc,SourceLocation IdLoc,IdentifierInfo * Id,EnumDecl * PrevDecl,bool Scoped,bool ScopedUsingClassTag,bool Fixed)4537e5dd7070Spatrick EnumDecl::EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
4538e5dd7070Spatrick SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl,
4539e5dd7070Spatrick bool Scoped, bool ScopedUsingClassTag, bool Fixed)
4540e5dd7070Spatrick : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc) {
4541e5dd7070Spatrick assert(Scoped || !ScopedUsingClassTag);
4542e5dd7070Spatrick IntegerType = nullptr;
4543e5dd7070Spatrick setNumPositiveBits(0);
4544e5dd7070Spatrick setNumNegativeBits(0);
4545e5dd7070Spatrick setScoped(Scoped);
4546e5dd7070Spatrick setScopedUsingClassTag(ScopedUsingClassTag);
4547e5dd7070Spatrick setFixed(Fixed);
4548e5dd7070Spatrick setHasODRHash(false);
4549e5dd7070Spatrick ODRHash = 0;
4550e5dd7070Spatrick }
4551e5dd7070Spatrick
anchor()4552e5dd7070Spatrick void EnumDecl::anchor() {}
4553e5dd7070Spatrick
Create(ASTContext & C,DeclContext * DC,SourceLocation StartLoc,SourceLocation IdLoc,IdentifierInfo * Id,EnumDecl * PrevDecl,bool IsScoped,bool IsScopedUsingClassTag,bool IsFixed)4554e5dd7070Spatrick EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC,
4555e5dd7070Spatrick SourceLocation StartLoc, SourceLocation IdLoc,
4556e5dd7070Spatrick IdentifierInfo *Id,
4557e5dd7070Spatrick EnumDecl *PrevDecl, bool IsScoped,
4558e5dd7070Spatrick bool IsScopedUsingClassTag, bool IsFixed) {
4559e5dd7070Spatrick auto *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl,
4560e5dd7070Spatrick IsScoped, IsScopedUsingClassTag, IsFixed);
4561e5dd7070Spatrick Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
4562e5dd7070Spatrick C.getTypeDeclType(Enum, PrevDecl);
4563e5dd7070Spatrick return Enum;
4564e5dd7070Spatrick }
4565e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID)4566e5dd7070Spatrick EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
4567e5dd7070Spatrick EnumDecl *Enum =
4568e5dd7070Spatrick new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(),
4569e5dd7070Spatrick nullptr, nullptr, false, false, false);
4570e5dd7070Spatrick Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
4571e5dd7070Spatrick return Enum;
4572e5dd7070Spatrick }
4573e5dd7070Spatrick
getIntegerTypeRange() const4574e5dd7070Spatrick SourceRange EnumDecl::getIntegerTypeRange() const {
4575e5dd7070Spatrick if (const TypeSourceInfo *TI = getIntegerTypeSourceInfo())
4576e5dd7070Spatrick return TI->getTypeLoc().getSourceRange();
4577e5dd7070Spatrick return SourceRange();
4578e5dd7070Spatrick }
4579e5dd7070Spatrick
completeDefinition(QualType NewType,QualType NewPromotionType,unsigned NumPositiveBits,unsigned NumNegativeBits)4580e5dd7070Spatrick void EnumDecl::completeDefinition(QualType NewType,
4581e5dd7070Spatrick QualType NewPromotionType,
4582e5dd7070Spatrick unsigned NumPositiveBits,
4583e5dd7070Spatrick unsigned NumNegativeBits) {
4584e5dd7070Spatrick assert(!isCompleteDefinition() && "Cannot redefine enums!");
4585e5dd7070Spatrick if (!IntegerType)
4586e5dd7070Spatrick IntegerType = NewType.getTypePtr();
4587e5dd7070Spatrick PromotionType = NewPromotionType;
4588e5dd7070Spatrick setNumPositiveBits(NumPositiveBits);
4589e5dd7070Spatrick setNumNegativeBits(NumNegativeBits);
4590e5dd7070Spatrick TagDecl::completeDefinition();
4591e5dd7070Spatrick }
4592e5dd7070Spatrick
isClosed() const4593e5dd7070Spatrick bool EnumDecl::isClosed() const {
4594e5dd7070Spatrick if (const auto *A = getAttr<EnumExtensibilityAttr>())
4595e5dd7070Spatrick return A->getExtensibility() == EnumExtensibilityAttr::Closed;
4596e5dd7070Spatrick return true;
4597e5dd7070Spatrick }
4598e5dd7070Spatrick
isClosedFlag() const4599e5dd7070Spatrick bool EnumDecl::isClosedFlag() const {
4600e5dd7070Spatrick return isClosed() && hasAttr<FlagEnumAttr>();
4601e5dd7070Spatrick }
4602e5dd7070Spatrick
isClosedNonFlag() const4603e5dd7070Spatrick bool EnumDecl::isClosedNonFlag() const {
4604e5dd7070Spatrick return isClosed() && !hasAttr<FlagEnumAttr>();
4605e5dd7070Spatrick }
4606e5dd7070Spatrick
getTemplateSpecializationKind() const4607e5dd7070Spatrick TemplateSpecializationKind EnumDecl::getTemplateSpecializationKind() const {
4608e5dd7070Spatrick if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
4609e5dd7070Spatrick return MSI->getTemplateSpecializationKind();
4610e5dd7070Spatrick
4611e5dd7070Spatrick return TSK_Undeclared;
4612e5dd7070Spatrick }
4613e5dd7070Spatrick
setTemplateSpecializationKind(TemplateSpecializationKind TSK,SourceLocation PointOfInstantiation)4614e5dd7070Spatrick void EnumDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
4615e5dd7070Spatrick SourceLocation PointOfInstantiation) {
4616e5dd7070Spatrick MemberSpecializationInfo *MSI = getMemberSpecializationInfo();
4617e5dd7070Spatrick assert(MSI && "Not an instantiated member enumeration?");
4618e5dd7070Spatrick MSI->setTemplateSpecializationKind(TSK);
4619e5dd7070Spatrick if (TSK != TSK_ExplicitSpecialization &&
4620e5dd7070Spatrick PointOfInstantiation.isValid() &&
4621e5dd7070Spatrick MSI->getPointOfInstantiation().isInvalid())
4622e5dd7070Spatrick MSI->setPointOfInstantiation(PointOfInstantiation);
4623e5dd7070Spatrick }
4624e5dd7070Spatrick
getTemplateInstantiationPattern() const4625e5dd7070Spatrick EnumDecl *EnumDecl::getTemplateInstantiationPattern() const {
4626e5dd7070Spatrick if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
4627e5dd7070Spatrick if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) {
4628e5dd7070Spatrick EnumDecl *ED = getInstantiatedFromMemberEnum();
4629e5dd7070Spatrick while (auto *NewED = ED->getInstantiatedFromMemberEnum())
4630e5dd7070Spatrick ED = NewED;
4631e5dd7070Spatrick return getDefinitionOrSelf(ED);
4632e5dd7070Spatrick }
4633e5dd7070Spatrick }
4634e5dd7070Spatrick
4635e5dd7070Spatrick assert(!isTemplateInstantiation(getTemplateSpecializationKind()) &&
4636e5dd7070Spatrick "couldn't find pattern for enum instantiation");
4637e5dd7070Spatrick return nullptr;
4638e5dd7070Spatrick }
4639e5dd7070Spatrick
getInstantiatedFromMemberEnum() const4640e5dd7070Spatrick EnumDecl *EnumDecl::getInstantiatedFromMemberEnum() const {
4641e5dd7070Spatrick if (SpecializationInfo)
4642e5dd7070Spatrick return cast<EnumDecl>(SpecializationInfo->getInstantiatedFrom());
4643e5dd7070Spatrick
4644e5dd7070Spatrick return nullptr;
4645e5dd7070Spatrick }
4646e5dd7070Spatrick
setInstantiationOfMemberEnum(ASTContext & C,EnumDecl * ED,TemplateSpecializationKind TSK)4647e5dd7070Spatrick void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
4648e5dd7070Spatrick TemplateSpecializationKind TSK) {
4649e5dd7070Spatrick assert(!SpecializationInfo && "Member enum is already a specialization");
4650e5dd7070Spatrick SpecializationInfo = new (C) MemberSpecializationInfo(ED, TSK);
4651e5dd7070Spatrick }
4652e5dd7070Spatrick
getODRHash()4653e5dd7070Spatrick unsigned EnumDecl::getODRHash() {
4654e5dd7070Spatrick if (hasODRHash())
4655e5dd7070Spatrick return ODRHash;
4656e5dd7070Spatrick
4657e5dd7070Spatrick class ODRHash Hash;
4658e5dd7070Spatrick Hash.AddEnumDecl(this);
4659e5dd7070Spatrick setHasODRHash(true);
4660e5dd7070Spatrick ODRHash = Hash.CalculateHash();
4661e5dd7070Spatrick return ODRHash;
4662e5dd7070Spatrick }
4663e5dd7070Spatrick
getSourceRange() const4664*12c85518Srobert SourceRange EnumDecl::getSourceRange() const {
4665*12c85518Srobert auto Res = TagDecl::getSourceRange();
4666*12c85518Srobert // Set end-point to enum-base, e.g. enum foo : ^bar
4667*12c85518Srobert if (auto *TSI = getIntegerTypeSourceInfo()) {
4668*12c85518Srobert // TagDecl doesn't know about the enum base.
4669*12c85518Srobert if (!getBraceRange().getEnd().isValid())
4670*12c85518Srobert Res.setEnd(TSI->getTypeLoc().getEndLoc());
4671*12c85518Srobert }
4672*12c85518Srobert return Res;
4673*12c85518Srobert }
4674*12c85518Srobert
getValueRange(llvm::APInt & Max,llvm::APInt & Min) const4675*12c85518Srobert void EnumDecl::getValueRange(llvm::APInt &Max, llvm::APInt &Min) const {
4676*12c85518Srobert unsigned Bitwidth = getASTContext().getIntWidth(getIntegerType());
4677*12c85518Srobert unsigned NumNegativeBits = getNumNegativeBits();
4678*12c85518Srobert unsigned NumPositiveBits = getNumPositiveBits();
4679*12c85518Srobert
4680*12c85518Srobert if (NumNegativeBits) {
4681*12c85518Srobert unsigned NumBits = std::max(NumNegativeBits, NumPositiveBits + 1);
4682*12c85518Srobert Max = llvm::APInt(Bitwidth, 1) << (NumBits - 1);
4683*12c85518Srobert Min = -Max;
4684*12c85518Srobert } else {
4685*12c85518Srobert Max = llvm::APInt(Bitwidth, 1) << NumPositiveBits;
4686*12c85518Srobert Min = llvm::APInt::getZero(Bitwidth);
4687*12c85518Srobert }
4688*12c85518Srobert }
4689*12c85518Srobert
4690e5dd7070Spatrick //===----------------------------------------------------------------------===//
4691e5dd7070Spatrick // RecordDecl Implementation
4692e5dd7070Spatrick //===----------------------------------------------------------------------===//
4693e5dd7070Spatrick
RecordDecl(Kind DK,TagKind TK,const ASTContext & C,DeclContext * DC,SourceLocation StartLoc,SourceLocation IdLoc,IdentifierInfo * Id,RecordDecl * PrevDecl)4694e5dd7070Spatrick RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C,
4695e5dd7070Spatrick DeclContext *DC, SourceLocation StartLoc,
4696e5dd7070Spatrick SourceLocation IdLoc, IdentifierInfo *Id,
4697e5dd7070Spatrick RecordDecl *PrevDecl)
4698e5dd7070Spatrick : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc) {
4699e5dd7070Spatrick assert(classof(static_cast<Decl *>(this)) && "Invalid Kind!");
4700e5dd7070Spatrick setHasFlexibleArrayMember(false);
4701e5dd7070Spatrick setAnonymousStructOrUnion(false);
4702e5dd7070Spatrick setHasObjectMember(false);
4703e5dd7070Spatrick setHasVolatileMember(false);
4704e5dd7070Spatrick setHasLoadedFieldsFromExternalStorage(false);
4705e5dd7070Spatrick setNonTrivialToPrimitiveDefaultInitialize(false);
4706e5dd7070Spatrick setNonTrivialToPrimitiveCopy(false);
4707e5dd7070Spatrick setNonTrivialToPrimitiveDestroy(false);
4708e5dd7070Spatrick setHasNonTrivialToPrimitiveDefaultInitializeCUnion(false);
4709e5dd7070Spatrick setHasNonTrivialToPrimitiveDestructCUnion(false);
4710e5dd7070Spatrick setHasNonTrivialToPrimitiveCopyCUnion(false);
4711e5dd7070Spatrick setParamDestroyedInCallee(false);
4712e5dd7070Spatrick setArgPassingRestrictions(APK_CanPassInRegs);
4713*12c85518Srobert setIsRandomized(false);
4714*12c85518Srobert setODRHash(0);
4715e5dd7070Spatrick }
4716e5dd7070Spatrick
Create(const ASTContext & C,TagKind TK,DeclContext * DC,SourceLocation StartLoc,SourceLocation IdLoc,IdentifierInfo * Id,RecordDecl * PrevDecl)4717e5dd7070Spatrick RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC,
4718e5dd7070Spatrick SourceLocation StartLoc, SourceLocation IdLoc,
4719e5dd7070Spatrick IdentifierInfo *Id, RecordDecl* PrevDecl) {
4720e5dd7070Spatrick RecordDecl *R = new (C, DC) RecordDecl(Record, TK, C, DC,
4721e5dd7070Spatrick StartLoc, IdLoc, Id, PrevDecl);
4722e5dd7070Spatrick R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
4723e5dd7070Spatrick
4724e5dd7070Spatrick C.getTypeDeclType(R, PrevDecl);
4725e5dd7070Spatrick return R;
4726e5dd7070Spatrick }
4727e5dd7070Spatrick
CreateDeserialized(const ASTContext & C,unsigned ID)4728e5dd7070Spatrick RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
4729e5dd7070Spatrick RecordDecl *R =
4730e5dd7070Spatrick new (C, ID) RecordDecl(Record, TTK_Struct, C, nullptr, SourceLocation(),
4731e5dd7070Spatrick SourceLocation(), nullptr, nullptr);
4732e5dd7070Spatrick R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
4733e5dd7070Spatrick return R;
4734e5dd7070Spatrick }
4735e5dd7070Spatrick
isInjectedClassName() const4736e5dd7070Spatrick bool RecordDecl::isInjectedClassName() const {
4737e5dd7070Spatrick return isImplicit() && getDeclName() && getDeclContext()->isRecord() &&
4738e5dd7070Spatrick cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName();
4739e5dd7070Spatrick }
4740e5dd7070Spatrick
isLambda() const4741e5dd7070Spatrick bool RecordDecl::isLambda() const {
4742e5dd7070Spatrick if (auto RD = dyn_cast<CXXRecordDecl>(this))
4743e5dd7070Spatrick return RD->isLambda();
4744e5dd7070Spatrick return false;
4745e5dd7070Spatrick }
4746e5dd7070Spatrick
isCapturedRecord() const4747e5dd7070Spatrick bool RecordDecl::isCapturedRecord() const {
4748e5dd7070Spatrick return hasAttr<CapturedRecordAttr>();
4749e5dd7070Spatrick }
4750e5dd7070Spatrick
setCapturedRecord()4751e5dd7070Spatrick void RecordDecl::setCapturedRecord() {
4752e5dd7070Spatrick addAttr(CapturedRecordAttr::CreateImplicit(getASTContext()));
4753e5dd7070Spatrick }
4754e5dd7070Spatrick
isOrContainsUnion() const4755ec727ea7Spatrick bool RecordDecl::isOrContainsUnion() const {
4756ec727ea7Spatrick if (isUnion())
4757ec727ea7Spatrick return true;
4758ec727ea7Spatrick
4759ec727ea7Spatrick if (const RecordDecl *Def = getDefinition()) {
4760ec727ea7Spatrick for (const FieldDecl *FD : Def->fields()) {
4761ec727ea7Spatrick const RecordType *RT = FD->getType()->getAs<RecordType>();
4762ec727ea7Spatrick if (RT && RT->getDecl()->isOrContainsUnion())
4763ec727ea7Spatrick return true;
4764ec727ea7Spatrick }
4765ec727ea7Spatrick }
4766ec727ea7Spatrick
4767ec727ea7Spatrick return false;
4768ec727ea7Spatrick }
4769ec727ea7Spatrick
field_begin() const4770e5dd7070Spatrick RecordDecl::field_iterator RecordDecl::field_begin() const {
4771e5dd7070Spatrick if (hasExternalLexicalStorage() && !hasLoadedFieldsFromExternalStorage())
4772e5dd7070Spatrick LoadFieldsFromExternalStorage();
4773e5dd7070Spatrick
4774e5dd7070Spatrick return field_iterator(decl_iterator(FirstDecl));
4775e5dd7070Spatrick }
4776e5dd7070Spatrick
4777e5dd7070Spatrick /// completeDefinition - Notes that the definition of this type is now
4778e5dd7070Spatrick /// complete.
completeDefinition()4779e5dd7070Spatrick void RecordDecl::completeDefinition() {
4780e5dd7070Spatrick assert(!isCompleteDefinition() && "Cannot redefine record!");
4781e5dd7070Spatrick TagDecl::completeDefinition();
4782a9ac8606Spatrick
4783a9ac8606Spatrick ASTContext &Ctx = getASTContext();
4784a9ac8606Spatrick
4785a9ac8606Spatrick // Layouts are dumped when computed, so if we are dumping for all complete
4786a9ac8606Spatrick // types, we need to force usage to get types that wouldn't be used elsewhere.
4787a9ac8606Spatrick if (Ctx.getLangOpts().DumpRecordLayoutsComplete)
4788a9ac8606Spatrick (void)Ctx.getASTRecordLayout(this);
4789e5dd7070Spatrick }
4790e5dd7070Spatrick
4791e5dd7070Spatrick /// isMsStruct - Get whether or not this record uses ms_struct layout.
4792e5dd7070Spatrick /// This which can be turned on with an attribute, pragma, or the
4793e5dd7070Spatrick /// -mms-bitfields command-line option.
isMsStruct(const ASTContext & C) const4794e5dd7070Spatrick bool RecordDecl::isMsStruct(const ASTContext &C) const {
4795e5dd7070Spatrick return hasAttr<MSStructAttr>() || C.getLangOpts().MSBitfields == 1;
4796e5dd7070Spatrick }
4797e5dd7070Spatrick
reorderDecls(const SmallVectorImpl<Decl * > & Decls)4798*12c85518Srobert void RecordDecl::reorderDecls(const SmallVectorImpl<Decl *> &Decls) {
4799*12c85518Srobert std::tie(FirstDecl, LastDecl) = DeclContext::BuildDeclChain(Decls, false);
4800*12c85518Srobert LastDecl->NextInContextAndBits.setPointer(nullptr);
4801*12c85518Srobert setIsRandomized(true);
4802*12c85518Srobert }
4803*12c85518Srobert
LoadFieldsFromExternalStorage() const4804e5dd7070Spatrick void RecordDecl::LoadFieldsFromExternalStorage() const {
4805e5dd7070Spatrick ExternalASTSource *Source = getASTContext().getExternalSource();
4806e5dd7070Spatrick assert(hasExternalLexicalStorage() && Source && "No external storage?");
4807e5dd7070Spatrick
4808e5dd7070Spatrick // Notify that we have a RecordDecl doing some initialization.
4809e5dd7070Spatrick ExternalASTSource::Deserializing TheFields(Source);
4810e5dd7070Spatrick
4811e5dd7070Spatrick SmallVector<Decl*, 64> Decls;
4812e5dd7070Spatrick setHasLoadedFieldsFromExternalStorage(true);
4813e5dd7070Spatrick Source->FindExternalLexicalDecls(this, [](Decl::Kind K) {
4814e5dd7070Spatrick return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K);
4815e5dd7070Spatrick }, Decls);
4816e5dd7070Spatrick
4817e5dd7070Spatrick #ifndef NDEBUG
4818e5dd7070Spatrick // Check that all decls we got were FieldDecls.
4819e5dd7070Spatrick for (unsigned i=0, e=Decls.size(); i != e; ++i)
4820e5dd7070Spatrick assert(isa<FieldDecl>(Decls[i]) || isa<IndirectFieldDecl>(Decls[i]));
4821e5dd7070Spatrick #endif
4822e5dd7070Spatrick
4823e5dd7070Spatrick if (Decls.empty())
4824e5dd7070Spatrick return;
4825e5dd7070Spatrick
4826e5dd7070Spatrick std::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls,
4827e5dd7070Spatrick /*FieldsAlreadyLoaded=*/false);
4828e5dd7070Spatrick }
4829e5dd7070Spatrick
mayInsertExtraPadding(bool EmitRemark) const4830e5dd7070Spatrick bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const {
4831e5dd7070Spatrick ASTContext &Context = getASTContext();
4832e5dd7070Spatrick const SanitizerMask EnabledAsanMask = Context.getLangOpts().Sanitize.Mask &
4833e5dd7070Spatrick (SanitizerKind::Address | SanitizerKind::KernelAddress);
4834e5dd7070Spatrick if (!EnabledAsanMask || !Context.getLangOpts().SanitizeAddressFieldPadding)
4835e5dd7070Spatrick return false;
4836a9ac8606Spatrick const auto &NoSanitizeList = Context.getNoSanitizeList();
4837e5dd7070Spatrick const auto *CXXRD = dyn_cast<CXXRecordDecl>(this);
4838e5dd7070Spatrick // We may be able to relax some of these requirements.
4839e5dd7070Spatrick int ReasonToReject = -1;
4840e5dd7070Spatrick if (!CXXRD || CXXRD->isExternCContext())
4841e5dd7070Spatrick ReasonToReject = 0; // is not C++.
4842e5dd7070Spatrick else if (CXXRD->hasAttr<PackedAttr>())
4843e5dd7070Spatrick ReasonToReject = 1; // is packed.
4844e5dd7070Spatrick else if (CXXRD->isUnion())
4845e5dd7070Spatrick ReasonToReject = 2; // is a union.
4846e5dd7070Spatrick else if (CXXRD->isTriviallyCopyable())
4847e5dd7070Spatrick ReasonToReject = 3; // is trivially copyable.
4848e5dd7070Spatrick else if (CXXRD->hasTrivialDestructor())
4849e5dd7070Spatrick ReasonToReject = 4; // has trivial destructor.
4850e5dd7070Spatrick else if (CXXRD->isStandardLayout())
4851e5dd7070Spatrick ReasonToReject = 5; // is standard layout.
4852a9ac8606Spatrick else if (NoSanitizeList.containsLocation(EnabledAsanMask, getLocation(),
4853e5dd7070Spatrick "field-padding"))
4854ec727ea7Spatrick ReasonToReject = 6; // is in an excluded file.
4855a9ac8606Spatrick else if (NoSanitizeList.containsType(
4856a9ac8606Spatrick EnabledAsanMask, getQualifiedNameAsString(), "field-padding"))
4857ec727ea7Spatrick ReasonToReject = 7; // The type is excluded.
4858e5dd7070Spatrick
4859e5dd7070Spatrick if (EmitRemark) {
4860e5dd7070Spatrick if (ReasonToReject >= 0)
4861e5dd7070Spatrick Context.getDiagnostics().Report(
4862e5dd7070Spatrick getLocation(),
4863e5dd7070Spatrick diag::remark_sanitize_address_insert_extra_padding_rejected)
4864e5dd7070Spatrick << getQualifiedNameAsString() << ReasonToReject;
4865e5dd7070Spatrick else
4866e5dd7070Spatrick Context.getDiagnostics().Report(
4867e5dd7070Spatrick getLocation(),
4868e5dd7070Spatrick diag::remark_sanitize_address_insert_extra_padding_accepted)
4869e5dd7070Spatrick << getQualifiedNameAsString();
4870e5dd7070Spatrick }
4871e5dd7070Spatrick return ReasonToReject < 0;
4872e5dd7070Spatrick }
4873e5dd7070Spatrick
findFirstNamedDataMember() const4874e5dd7070Spatrick const FieldDecl *RecordDecl::findFirstNamedDataMember() const {
4875e5dd7070Spatrick for (const auto *I : fields()) {
4876e5dd7070Spatrick if (I->getIdentifier())
4877e5dd7070Spatrick return I;
4878e5dd7070Spatrick
4879e5dd7070Spatrick if (const auto *RT = I->getType()->getAs<RecordType>())
4880e5dd7070Spatrick if (const FieldDecl *NamedDataMember =
4881e5dd7070Spatrick RT->getDecl()->findFirstNamedDataMember())
4882e5dd7070Spatrick return NamedDataMember;
4883e5dd7070Spatrick }
4884e5dd7070Spatrick
4885e5dd7070Spatrick // We didn't find a named data member.
4886e5dd7070Spatrick return nullptr;
4887e5dd7070Spatrick }
4888e5dd7070Spatrick
getODRHash()4889*12c85518Srobert unsigned RecordDecl::getODRHash() {
4890*12c85518Srobert if (hasODRHash())
4891*12c85518Srobert return RecordDeclBits.ODRHash;
4892*12c85518Srobert
4893*12c85518Srobert // Only calculate hash on first call of getODRHash per record.
4894*12c85518Srobert ODRHash Hash;
4895*12c85518Srobert Hash.AddRecordDecl(this);
4896*12c85518Srobert // For RecordDecl the ODRHash is stored in the remaining 26
4897*12c85518Srobert // bit of RecordDeclBits, adjust the hash to accomodate.
4898*12c85518Srobert setODRHash(Hash.CalculateHash() >> 6);
4899*12c85518Srobert return RecordDeclBits.ODRHash;
4900*12c85518Srobert }
4901*12c85518Srobert
4902e5dd7070Spatrick //===----------------------------------------------------------------------===//
4903e5dd7070Spatrick // BlockDecl Implementation
4904e5dd7070Spatrick //===----------------------------------------------------------------------===//
4905e5dd7070Spatrick
BlockDecl(DeclContext * DC,SourceLocation CaretLoc)4906e5dd7070Spatrick BlockDecl::BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
4907e5dd7070Spatrick : Decl(Block, DC, CaretLoc), DeclContext(Block) {
4908e5dd7070Spatrick setIsVariadic(false);
4909e5dd7070Spatrick setCapturesCXXThis(false);
4910e5dd7070Spatrick setBlockMissingReturnType(true);
4911e5dd7070Spatrick setIsConversionFromLambda(false);
4912e5dd7070Spatrick setDoesNotEscape(false);
4913e5dd7070Spatrick setCanAvoidCopyToHeap(false);
4914e5dd7070Spatrick }
4915e5dd7070Spatrick
setParams(ArrayRef<ParmVarDecl * > NewParamInfo)4916e5dd7070Spatrick void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) {
4917e5dd7070Spatrick assert(!ParamInfo && "Already has param info!");
4918e5dd7070Spatrick
4919e5dd7070Spatrick // Zero params -> null pointer.
4920e5dd7070Spatrick if (!NewParamInfo.empty()) {
4921e5dd7070Spatrick NumParams = NewParamInfo.size();
4922e5dd7070Spatrick ParamInfo = new (getASTContext()) ParmVarDecl*[NewParamInfo.size()];
4923e5dd7070Spatrick std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo);
4924e5dd7070Spatrick }
4925e5dd7070Spatrick }
4926e5dd7070Spatrick
setCaptures(ASTContext & Context,ArrayRef<Capture> Captures,bool CapturesCXXThis)4927e5dd7070Spatrick void BlockDecl::setCaptures(ASTContext &Context, ArrayRef<Capture> Captures,
4928e5dd7070Spatrick bool CapturesCXXThis) {
4929e5dd7070Spatrick this->setCapturesCXXThis(CapturesCXXThis);
4930e5dd7070Spatrick this->NumCaptures = Captures.size();
4931e5dd7070Spatrick
4932e5dd7070Spatrick if (Captures.empty()) {
4933e5dd7070Spatrick this->Captures = nullptr;
4934e5dd7070Spatrick return;
4935e5dd7070Spatrick }
4936e5dd7070Spatrick
4937e5dd7070Spatrick this->Captures = Captures.copy(Context).data();
4938e5dd7070Spatrick }
4939e5dd7070Spatrick
capturesVariable(const VarDecl * variable) const4940e5dd7070Spatrick bool BlockDecl::capturesVariable(const VarDecl *variable) const {
4941e5dd7070Spatrick for (const auto &I : captures())
4942e5dd7070Spatrick // Only auto vars can be captured, so no redeclaration worries.
4943e5dd7070Spatrick if (I.getVariable() == variable)
4944e5dd7070Spatrick return true;
4945e5dd7070Spatrick
4946e5dd7070Spatrick return false;
4947e5dd7070Spatrick }
4948e5dd7070Spatrick
getSourceRange() const4949e5dd7070Spatrick SourceRange BlockDecl::getSourceRange() const {
4950e5dd7070Spatrick return SourceRange(getLocation(), Body ? Body->getEndLoc() : getLocation());
4951e5dd7070Spatrick }
4952e5dd7070Spatrick
4953e5dd7070Spatrick //===----------------------------------------------------------------------===//
4954e5dd7070Spatrick // Other Decl Allocation/Deallocation Method Implementations
4955e5dd7070Spatrick //===----------------------------------------------------------------------===//
4956e5dd7070Spatrick
anchor()4957e5dd7070Spatrick void TranslationUnitDecl::anchor() {}
4958e5dd7070Spatrick
Create(ASTContext & C)4959e5dd7070Spatrick TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
4960e5dd7070Spatrick return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C);
4961e5dd7070Spatrick }
4962e5dd7070Spatrick
anchor()4963e5dd7070Spatrick void PragmaCommentDecl::anchor() {}
4964e5dd7070Spatrick
Create(const ASTContext & C,TranslationUnitDecl * DC,SourceLocation CommentLoc,PragmaMSCommentKind CommentKind,StringRef Arg)4965e5dd7070Spatrick PragmaCommentDecl *PragmaCommentDecl::Create(const ASTContext &C,
4966e5dd7070Spatrick TranslationUnitDecl *DC,
4967e5dd7070Spatrick SourceLocation CommentLoc,
4968e5dd7070Spatrick PragmaMSCommentKind CommentKind,
4969e5dd7070Spatrick StringRef Arg) {
4970e5dd7070Spatrick PragmaCommentDecl *PCD =
4971e5dd7070Spatrick new (C, DC, additionalSizeToAlloc<char>(Arg.size() + 1))
4972e5dd7070Spatrick PragmaCommentDecl(DC, CommentLoc, CommentKind);
4973e5dd7070Spatrick memcpy(PCD->getTrailingObjects<char>(), Arg.data(), Arg.size());
4974e5dd7070Spatrick PCD->getTrailingObjects<char>()[Arg.size()] = '\0';
4975e5dd7070Spatrick return PCD;
4976e5dd7070Spatrick }
4977e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID,unsigned ArgSize)4978e5dd7070Spatrick PragmaCommentDecl *PragmaCommentDecl::CreateDeserialized(ASTContext &C,
4979e5dd7070Spatrick unsigned ID,
4980e5dd7070Spatrick unsigned ArgSize) {
4981e5dd7070Spatrick return new (C, ID, additionalSizeToAlloc<char>(ArgSize + 1))
4982e5dd7070Spatrick PragmaCommentDecl(nullptr, SourceLocation(), PCK_Unknown);
4983e5dd7070Spatrick }
4984e5dd7070Spatrick
anchor()4985e5dd7070Spatrick void PragmaDetectMismatchDecl::anchor() {}
4986e5dd7070Spatrick
4987e5dd7070Spatrick PragmaDetectMismatchDecl *
Create(const ASTContext & C,TranslationUnitDecl * DC,SourceLocation Loc,StringRef Name,StringRef Value)4988e5dd7070Spatrick PragmaDetectMismatchDecl::Create(const ASTContext &C, TranslationUnitDecl *DC,
4989e5dd7070Spatrick SourceLocation Loc, StringRef Name,
4990e5dd7070Spatrick StringRef Value) {
4991e5dd7070Spatrick size_t ValueStart = Name.size() + 1;
4992e5dd7070Spatrick PragmaDetectMismatchDecl *PDMD =
4993e5dd7070Spatrick new (C, DC, additionalSizeToAlloc<char>(ValueStart + Value.size() + 1))
4994e5dd7070Spatrick PragmaDetectMismatchDecl(DC, Loc, ValueStart);
4995e5dd7070Spatrick memcpy(PDMD->getTrailingObjects<char>(), Name.data(), Name.size());
4996e5dd7070Spatrick PDMD->getTrailingObjects<char>()[Name.size()] = '\0';
4997e5dd7070Spatrick memcpy(PDMD->getTrailingObjects<char>() + ValueStart, Value.data(),
4998e5dd7070Spatrick Value.size());
4999e5dd7070Spatrick PDMD->getTrailingObjects<char>()[ValueStart + Value.size()] = '\0';
5000e5dd7070Spatrick return PDMD;
5001e5dd7070Spatrick }
5002e5dd7070Spatrick
5003e5dd7070Spatrick PragmaDetectMismatchDecl *
CreateDeserialized(ASTContext & C,unsigned ID,unsigned NameValueSize)5004e5dd7070Spatrick PragmaDetectMismatchDecl::CreateDeserialized(ASTContext &C, unsigned ID,
5005e5dd7070Spatrick unsigned NameValueSize) {
5006e5dd7070Spatrick return new (C, ID, additionalSizeToAlloc<char>(NameValueSize + 1))
5007e5dd7070Spatrick PragmaDetectMismatchDecl(nullptr, SourceLocation(), 0);
5008e5dd7070Spatrick }
5009e5dd7070Spatrick
anchor()5010e5dd7070Spatrick void ExternCContextDecl::anchor() {}
5011e5dd7070Spatrick
Create(const ASTContext & C,TranslationUnitDecl * DC)5012e5dd7070Spatrick ExternCContextDecl *ExternCContextDecl::Create(const ASTContext &C,
5013e5dd7070Spatrick TranslationUnitDecl *DC) {
5014e5dd7070Spatrick return new (C, DC) ExternCContextDecl(DC);
5015e5dd7070Spatrick }
5016e5dd7070Spatrick
anchor()5017e5dd7070Spatrick void LabelDecl::anchor() {}
5018e5dd7070Spatrick
Create(ASTContext & C,DeclContext * DC,SourceLocation IdentL,IdentifierInfo * II)5019e5dd7070Spatrick LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
5020e5dd7070Spatrick SourceLocation IdentL, IdentifierInfo *II) {
5021e5dd7070Spatrick return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, IdentL);
5022e5dd7070Spatrick }
5023e5dd7070Spatrick
Create(ASTContext & C,DeclContext * DC,SourceLocation IdentL,IdentifierInfo * II,SourceLocation GnuLabelL)5024e5dd7070Spatrick LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
5025e5dd7070Spatrick SourceLocation IdentL, IdentifierInfo *II,
5026e5dd7070Spatrick SourceLocation GnuLabelL) {
5027e5dd7070Spatrick assert(GnuLabelL != IdentL && "Use this only for GNU local labels");
5028e5dd7070Spatrick return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, GnuLabelL);
5029e5dd7070Spatrick }
5030e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID)5031e5dd7070Spatrick LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
5032e5dd7070Spatrick return new (C, ID) LabelDecl(nullptr, SourceLocation(), nullptr, nullptr,
5033e5dd7070Spatrick SourceLocation());
5034e5dd7070Spatrick }
5035e5dd7070Spatrick
setMSAsmLabel(StringRef Name)5036e5dd7070Spatrick void LabelDecl::setMSAsmLabel(StringRef Name) {
5037e5dd7070Spatrick char *Buffer = new (getASTContext(), 1) char[Name.size() + 1];
5038e5dd7070Spatrick memcpy(Buffer, Name.data(), Name.size());
5039e5dd7070Spatrick Buffer[Name.size()] = '\0';
5040e5dd7070Spatrick MSAsmName = Buffer;
5041e5dd7070Spatrick }
5042e5dd7070Spatrick
anchor()5043e5dd7070Spatrick void ValueDecl::anchor() {}
5044e5dd7070Spatrick
isWeak() const5045e5dd7070Spatrick bool ValueDecl::isWeak() const {
5046a9ac8606Spatrick auto *MostRecent = getMostRecentDecl();
5047a9ac8606Spatrick return MostRecent->hasAttr<WeakAttr>() ||
5048a9ac8606Spatrick MostRecent->hasAttr<WeakRefAttr>() || isWeakImported();
5049e5dd7070Spatrick }
5050e5dd7070Spatrick
isInitCapture() const5051*12c85518Srobert bool ValueDecl::isInitCapture() const {
5052*12c85518Srobert if (auto *Var = llvm::dyn_cast<VarDecl>(this))
5053*12c85518Srobert return Var->isInitCapture();
5054*12c85518Srobert return false;
5055*12c85518Srobert }
5056*12c85518Srobert
anchor()5057e5dd7070Spatrick void ImplicitParamDecl::anchor() {}
5058e5dd7070Spatrick
Create(ASTContext & C,DeclContext * DC,SourceLocation IdLoc,IdentifierInfo * Id,QualType Type,ImplicitParamKind ParamKind)5059e5dd7070Spatrick ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
5060e5dd7070Spatrick SourceLocation IdLoc,
5061e5dd7070Spatrick IdentifierInfo *Id, QualType Type,
5062e5dd7070Spatrick ImplicitParamKind ParamKind) {
5063e5dd7070Spatrick return new (C, DC) ImplicitParamDecl(C, DC, IdLoc, Id, Type, ParamKind);
5064e5dd7070Spatrick }
5065e5dd7070Spatrick
Create(ASTContext & C,QualType Type,ImplicitParamKind ParamKind)5066e5dd7070Spatrick ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, QualType Type,
5067e5dd7070Spatrick ImplicitParamKind ParamKind) {
5068e5dd7070Spatrick return new (C, nullptr) ImplicitParamDecl(C, Type, ParamKind);
5069e5dd7070Spatrick }
5070e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID)5071e5dd7070Spatrick ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C,
5072e5dd7070Spatrick unsigned ID) {
5073e5dd7070Spatrick return new (C, ID) ImplicitParamDecl(C, QualType(), ImplicitParamKind::Other);
5074e5dd7070Spatrick }
5075e5dd7070Spatrick
5076*12c85518Srobert 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)5077*12c85518Srobert FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
5078*12c85518Srobert const DeclarationNameInfo &NameInfo, QualType T,
5079*12c85518Srobert TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin,
5080*12c85518Srobert bool isInlineSpecified, bool hasWrittenPrototype,
5081e5dd7070Spatrick ConstexprSpecKind ConstexprKind,
5082e5dd7070Spatrick Expr *TrailingRequiresClause) {
5083*12c85518Srobert FunctionDecl *New = new (C, DC) FunctionDecl(
5084*12c85518Srobert Function, C, DC, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin,
5085*12c85518Srobert isInlineSpecified, ConstexprKind, TrailingRequiresClause);
5086e5dd7070Spatrick New->setHasWrittenPrototype(hasWrittenPrototype);
5087e5dd7070Spatrick return New;
5088e5dd7070Spatrick }
5089e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID)5090e5dd7070Spatrick FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
5091a9ac8606Spatrick return new (C, ID) FunctionDecl(
5092a9ac8606Spatrick Function, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(),
5093*12c85518Srobert nullptr, SC_None, false, false, ConstexprSpecKind::Unspecified, nullptr);
5094e5dd7070Spatrick }
5095e5dd7070Spatrick
Create(ASTContext & C,DeclContext * DC,SourceLocation L)5096e5dd7070Spatrick BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
5097e5dd7070Spatrick return new (C, DC) BlockDecl(DC, L);
5098e5dd7070Spatrick }
5099e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID)5100e5dd7070Spatrick BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
5101e5dd7070Spatrick return new (C, ID) BlockDecl(nullptr, SourceLocation());
5102e5dd7070Spatrick }
5103e5dd7070Spatrick
CapturedDecl(DeclContext * DC,unsigned NumParams)5104e5dd7070Spatrick CapturedDecl::CapturedDecl(DeclContext *DC, unsigned NumParams)
5105e5dd7070Spatrick : Decl(Captured, DC, SourceLocation()), DeclContext(Captured),
5106e5dd7070Spatrick NumParams(NumParams), ContextParam(0), BodyAndNothrow(nullptr, false) {}
5107e5dd7070Spatrick
Create(ASTContext & C,DeclContext * DC,unsigned NumParams)5108e5dd7070Spatrick CapturedDecl *CapturedDecl::Create(ASTContext &C, DeclContext *DC,
5109e5dd7070Spatrick unsigned NumParams) {
5110e5dd7070Spatrick return new (C, DC, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams))
5111e5dd7070Spatrick CapturedDecl(DC, NumParams);
5112e5dd7070Spatrick }
5113e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID,unsigned NumParams)5114e5dd7070Spatrick CapturedDecl *CapturedDecl::CreateDeserialized(ASTContext &C, unsigned ID,
5115e5dd7070Spatrick unsigned NumParams) {
5116e5dd7070Spatrick return new (C, ID, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams))
5117e5dd7070Spatrick CapturedDecl(nullptr, NumParams);
5118e5dd7070Spatrick }
5119e5dd7070Spatrick
getBody() const5120e5dd7070Spatrick Stmt *CapturedDecl::getBody() const { return BodyAndNothrow.getPointer(); }
setBody(Stmt * B)5121e5dd7070Spatrick void CapturedDecl::setBody(Stmt *B) { BodyAndNothrow.setPointer(B); }
5122e5dd7070Spatrick
isNothrow() const5123e5dd7070Spatrick bool CapturedDecl::isNothrow() const { return BodyAndNothrow.getInt(); }
setNothrow(bool Nothrow)5124e5dd7070Spatrick void CapturedDecl::setNothrow(bool Nothrow) { BodyAndNothrow.setInt(Nothrow); }
5125e5dd7070Spatrick
Create(ASTContext & C,EnumDecl * CD,SourceLocation L,IdentifierInfo * Id,QualType T,Expr * E,const llvm::APSInt & V)5126e5dd7070Spatrick EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
5127e5dd7070Spatrick SourceLocation L,
5128e5dd7070Spatrick IdentifierInfo *Id, QualType T,
5129e5dd7070Spatrick Expr *E, const llvm::APSInt &V) {
5130e5dd7070Spatrick return new (C, CD) EnumConstantDecl(CD, L, Id, T, E, V);
5131e5dd7070Spatrick }
5132e5dd7070Spatrick
5133e5dd7070Spatrick EnumConstantDecl *
CreateDeserialized(ASTContext & C,unsigned ID)5134e5dd7070Spatrick EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
5135e5dd7070Spatrick return new (C, ID) EnumConstantDecl(nullptr, SourceLocation(), nullptr,
5136e5dd7070Spatrick QualType(), nullptr, llvm::APSInt());
5137e5dd7070Spatrick }
5138e5dd7070Spatrick
anchor()5139e5dd7070Spatrick void IndirectFieldDecl::anchor() {}
5140e5dd7070Spatrick
IndirectFieldDecl(ASTContext & C,DeclContext * DC,SourceLocation L,DeclarationName N,QualType T,MutableArrayRef<NamedDecl * > CH)5141e5dd7070Spatrick IndirectFieldDecl::IndirectFieldDecl(ASTContext &C, DeclContext *DC,
5142e5dd7070Spatrick SourceLocation L, DeclarationName N,
5143e5dd7070Spatrick QualType T,
5144e5dd7070Spatrick MutableArrayRef<NamedDecl *> CH)
5145e5dd7070Spatrick : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH.data()),
5146e5dd7070Spatrick ChainingSize(CH.size()) {
5147e5dd7070Spatrick // In C++, indirect field declarations conflict with tag declarations in the
5148e5dd7070Spatrick // same scope, so add them to IDNS_Tag so that tag redeclaration finds them.
5149e5dd7070Spatrick if (C.getLangOpts().CPlusPlus)
5150e5dd7070Spatrick IdentifierNamespace |= IDNS_Tag;
5151e5dd7070Spatrick }
5152e5dd7070Spatrick
5153e5dd7070Spatrick IndirectFieldDecl *
Create(ASTContext & C,DeclContext * DC,SourceLocation L,IdentifierInfo * Id,QualType T,llvm::MutableArrayRef<NamedDecl * > CH)5154e5dd7070Spatrick IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
5155e5dd7070Spatrick IdentifierInfo *Id, QualType T,
5156e5dd7070Spatrick llvm::MutableArrayRef<NamedDecl *> CH) {
5157e5dd7070Spatrick return new (C, DC) IndirectFieldDecl(C, DC, L, Id, T, CH);
5158e5dd7070Spatrick }
5159e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID)5160e5dd7070Spatrick IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C,
5161e5dd7070Spatrick unsigned ID) {
5162*12c85518Srobert return new (C, ID)
5163*12c85518Srobert IndirectFieldDecl(C, nullptr, SourceLocation(), DeclarationName(),
5164*12c85518Srobert QualType(), std::nullopt);
5165e5dd7070Spatrick }
5166e5dd7070Spatrick
getSourceRange() const5167e5dd7070Spatrick SourceRange EnumConstantDecl::getSourceRange() const {
5168e5dd7070Spatrick SourceLocation End = getLocation();
5169e5dd7070Spatrick if (Init)
5170e5dd7070Spatrick End = Init->getEndLoc();
5171e5dd7070Spatrick return SourceRange(getLocation(), End);
5172e5dd7070Spatrick }
5173e5dd7070Spatrick
anchor()5174e5dd7070Spatrick void TypeDecl::anchor() {}
5175e5dd7070Spatrick
Create(ASTContext & C,DeclContext * DC,SourceLocation StartLoc,SourceLocation IdLoc,IdentifierInfo * Id,TypeSourceInfo * TInfo)5176e5dd7070Spatrick TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
5177e5dd7070Spatrick SourceLocation StartLoc, SourceLocation IdLoc,
5178e5dd7070Spatrick IdentifierInfo *Id, TypeSourceInfo *TInfo) {
5179e5dd7070Spatrick return new (C, DC) TypedefDecl(C, DC, StartLoc, IdLoc, Id, TInfo);
5180e5dd7070Spatrick }
5181e5dd7070Spatrick
anchor()5182e5dd7070Spatrick void TypedefNameDecl::anchor() {}
5183e5dd7070Spatrick
getAnonDeclWithTypedefName(bool AnyRedecl) const5184e5dd7070Spatrick TagDecl *TypedefNameDecl::getAnonDeclWithTypedefName(bool AnyRedecl) const {
5185e5dd7070Spatrick if (auto *TT = getTypeSourceInfo()->getType()->getAs<TagType>()) {
5186e5dd7070Spatrick auto *OwningTypedef = TT->getDecl()->getTypedefNameForAnonDecl();
5187e5dd7070Spatrick auto *ThisTypedef = this;
5188e5dd7070Spatrick if (AnyRedecl && OwningTypedef) {
5189e5dd7070Spatrick OwningTypedef = OwningTypedef->getCanonicalDecl();
5190e5dd7070Spatrick ThisTypedef = ThisTypedef->getCanonicalDecl();
5191e5dd7070Spatrick }
5192e5dd7070Spatrick if (OwningTypedef == ThisTypedef)
5193e5dd7070Spatrick return TT->getDecl();
5194e5dd7070Spatrick }
5195e5dd7070Spatrick
5196e5dd7070Spatrick return nullptr;
5197e5dd7070Spatrick }
5198e5dd7070Spatrick
isTransparentTagSlow() const5199e5dd7070Spatrick bool TypedefNameDecl::isTransparentTagSlow() const {
5200e5dd7070Spatrick auto determineIsTransparent = [&]() {
5201e5dd7070Spatrick if (auto *TT = getUnderlyingType()->getAs<TagType>()) {
5202e5dd7070Spatrick if (auto *TD = TT->getDecl()) {
5203e5dd7070Spatrick if (TD->getName() != getName())
5204e5dd7070Spatrick return false;
5205e5dd7070Spatrick SourceLocation TTLoc = getLocation();
5206e5dd7070Spatrick SourceLocation TDLoc = TD->getLocation();
5207e5dd7070Spatrick if (!TTLoc.isMacroID() || !TDLoc.isMacroID())
5208e5dd7070Spatrick return false;
5209e5dd7070Spatrick SourceManager &SM = getASTContext().getSourceManager();
5210e5dd7070Spatrick return SM.getSpellingLoc(TTLoc) == SM.getSpellingLoc(TDLoc);
5211e5dd7070Spatrick }
5212e5dd7070Spatrick }
5213e5dd7070Spatrick return false;
5214e5dd7070Spatrick };
5215e5dd7070Spatrick
5216e5dd7070Spatrick bool isTransparent = determineIsTransparent();
5217e5dd7070Spatrick MaybeModedTInfo.setInt((isTransparent << 1) | 1);
5218e5dd7070Spatrick return isTransparent;
5219e5dd7070Spatrick }
5220e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID)5221e5dd7070Spatrick TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
5222e5dd7070Spatrick return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(),
5223e5dd7070Spatrick nullptr, nullptr);
5224e5dd7070Spatrick }
5225e5dd7070Spatrick
Create(ASTContext & C,DeclContext * DC,SourceLocation StartLoc,SourceLocation IdLoc,IdentifierInfo * Id,TypeSourceInfo * TInfo)5226e5dd7070Spatrick TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC,
5227e5dd7070Spatrick SourceLocation StartLoc,
5228e5dd7070Spatrick SourceLocation IdLoc, IdentifierInfo *Id,
5229e5dd7070Spatrick TypeSourceInfo *TInfo) {
5230e5dd7070Spatrick return new (C, DC) TypeAliasDecl(C, DC, StartLoc, IdLoc, Id, TInfo);
5231e5dd7070Spatrick }
5232e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID)5233e5dd7070Spatrick TypeAliasDecl *TypeAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
5234e5dd7070Spatrick return new (C, ID) TypeAliasDecl(C, nullptr, SourceLocation(),
5235e5dd7070Spatrick SourceLocation(), nullptr, nullptr);
5236e5dd7070Spatrick }
5237e5dd7070Spatrick
getSourceRange() const5238e5dd7070Spatrick SourceRange TypedefDecl::getSourceRange() const {
5239e5dd7070Spatrick SourceLocation RangeEnd = getLocation();
5240e5dd7070Spatrick if (TypeSourceInfo *TInfo = getTypeSourceInfo()) {
5241e5dd7070Spatrick if (typeIsPostfix(TInfo->getType()))
5242e5dd7070Spatrick RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd();
5243e5dd7070Spatrick }
5244e5dd7070Spatrick return SourceRange(getBeginLoc(), RangeEnd);
5245e5dd7070Spatrick }
5246e5dd7070Spatrick
getSourceRange() const5247e5dd7070Spatrick SourceRange TypeAliasDecl::getSourceRange() const {
5248e5dd7070Spatrick SourceLocation RangeEnd = getBeginLoc();
5249e5dd7070Spatrick if (TypeSourceInfo *TInfo = getTypeSourceInfo())
5250e5dd7070Spatrick RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd();
5251e5dd7070Spatrick return SourceRange(getBeginLoc(), RangeEnd);
5252e5dd7070Spatrick }
5253e5dd7070Spatrick
anchor()5254e5dd7070Spatrick void FileScopeAsmDecl::anchor() {}
5255e5dd7070Spatrick
Create(ASTContext & C,DeclContext * DC,StringLiteral * Str,SourceLocation AsmLoc,SourceLocation RParenLoc)5256e5dd7070Spatrick FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
5257e5dd7070Spatrick StringLiteral *Str,
5258e5dd7070Spatrick SourceLocation AsmLoc,
5259e5dd7070Spatrick SourceLocation RParenLoc) {
5260e5dd7070Spatrick return new (C, DC) FileScopeAsmDecl(DC, Str, AsmLoc, RParenLoc);
5261e5dd7070Spatrick }
5262e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID)5263e5dd7070Spatrick FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C,
5264e5dd7070Spatrick unsigned ID) {
5265e5dd7070Spatrick return new (C, ID) FileScopeAsmDecl(nullptr, nullptr, SourceLocation(),
5266e5dd7070Spatrick SourceLocation());
5267e5dd7070Spatrick }
5268e5dd7070Spatrick
anchor()5269*12c85518Srobert void TopLevelStmtDecl::anchor() {}
5270*12c85518Srobert
Create(ASTContext & C,Stmt * Statement)5271*12c85518Srobert TopLevelStmtDecl *TopLevelStmtDecl::Create(ASTContext &C, Stmt *Statement) {
5272*12c85518Srobert assert(Statement);
5273*12c85518Srobert assert(C.getLangOpts().IncrementalExtensions &&
5274*12c85518Srobert "Must be used only in incremental mode");
5275*12c85518Srobert
5276*12c85518Srobert SourceLocation BeginLoc = Statement->getBeginLoc();
5277*12c85518Srobert DeclContext *DC = C.getTranslationUnitDecl();
5278*12c85518Srobert
5279*12c85518Srobert return new (C, DC) TopLevelStmtDecl(DC, BeginLoc, Statement);
5280*12c85518Srobert }
5281*12c85518Srobert
CreateDeserialized(ASTContext & C,unsigned ID)5282*12c85518Srobert TopLevelStmtDecl *TopLevelStmtDecl::CreateDeserialized(ASTContext &C,
5283*12c85518Srobert unsigned ID) {
5284*12c85518Srobert return new (C, ID)
5285*12c85518Srobert TopLevelStmtDecl(/*DC=*/nullptr, SourceLocation(), /*S=*/nullptr);
5286*12c85518Srobert }
5287*12c85518Srobert
getSourceRange() const5288*12c85518Srobert SourceRange TopLevelStmtDecl::getSourceRange() const {
5289*12c85518Srobert return SourceRange(getLocation(), Statement->getEndLoc());
5290*12c85518Srobert }
5291*12c85518Srobert
anchor()5292e5dd7070Spatrick void EmptyDecl::anchor() {}
5293e5dd7070Spatrick
Create(ASTContext & C,DeclContext * DC,SourceLocation L)5294e5dd7070Spatrick EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
5295e5dd7070Spatrick return new (C, DC) EmptyDecl(DC, L);
5296e5dd7070Spatrick }
5297e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID)5298e5dd7070Spatrick EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
5299e5dd7070Spatrick return new (C, ID) EmptyDecl(nullptr, SourceLocation());
5300e5dd7070Spatrick }
5301e5dd7070Spatrick
HLSLBufferDecl(DeclContext * DC,bool CBuffer,SourceLocation KwLoc,IdentifierInfo * ID,SourceLocation IDLoc,SourceLocation LBrace)5302*12c85518Srobert HLSLBufferDecl::HLSLBufferDecl(DeclContext *DC, bool CBuffer,
5303*12c85518Srobert SourceLocation KwLoc, IdentifierInfo *ID,
5304*12c85518Srobert SourceLocation IDLoc, SourceLocation LBrace)
5305*12c85518Srobert : NamedDecl(Decl::Kind::HLSLBuffer, DC, IDLoc, DeclarationName(ID)),
5306*12c85518Srobert DeclContext(Decl::Kind::HLSLBuffer), LBraceLoc(LBrace), KwLoc(KwLoc),
5307*12c85518Srobert IsCBuffer(CBuffer) {}
5308*12c85518Srobert
Create(ASTContext & C,DeclContext * LexicalParent,bool CBuffer,SourceLocation KwLoc,IdentifierInfo * ID,SourceLocation IDLoc,SourceLocation LBrace)5309*12c85518Srobert HLSLBufferDecl *HLSLBufferDecl::Create(ASTContext &C,
5310*12c85518Srobert DeclContext *LexicalParent, bool CBuffer,
5311*12c85518Srobert SourceLocation KwLoc, IdentifierInfo *ID,
5312*12c85518Srobert SourceLocation IDLoc,
5313*12c85518Srobert SourceLocation LBrace) {
5314*12c85518Srobert // For hlsl like this
5315*12c85518Srobert // cbuffer A {
5316*12c85518Srobert // cbuffer B {
5317*12c85518Srobert // }
5318*12c85518Srobert // }
5319*12c85518Srobert // compiler should treat it as
5320*12c85518Srobert // cbuffer A {
5321*12c85518Srobert // }
5322*12c85518Srobert // cbuffer B {
5323*12c85518Srobert // }
5324*12c85518Srobert // FIXME: support nested buffers if required for back-compat.
5325*12c85518Srobert DeclContext *DC = LexicalParent;
5326*12c85518Srobert HLSLBufferDecl *Result =
5327*12c85518Srobert new (C, DC) HLSLBufferDecl(DC, CBuffer, KwLoc, ID, IDLoc, LBrace);
5328*12c85518Srobert return Result;
5329*12c85518Srobert }
5330*12c85518Srobert
CreateDeserialized(ASTContext & C,unsigned ID)5331*12c85518Srobert HLSLBufferDecl *HLSLBufferDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
5332*12c85518Srobert return new (C, ID) HLSLBufferDecl(nullptr, false, SourceLocation(), nullptr,
5333*12c85518Srobert SourceLocation(), SourceLocation());
5334*12c85518Srobert }
5335*12c85518Srobert
5336e5dd7070Spatrick //===----------------------------------------------------------------------===//
5337e5dd7070Spatrick // ImportDecl Implementation
5338e5dd7070Spatrick //===----------------------------------------------------------------------===//
5339e5dd7070Spatrick
5340e5dd7070Spatrick /// Retrieve the number of module identifiers needed to name the given
5341e5dd7070Spatrick /// module.
getNumModuleIdentifiers(Module * Mod)5342e5dd7070Spatrick static unsigned getNumModuleIdentifiers(Module *Mod) {
5343e5dd7070Spatrick unsigned Result = 1;
5344e5dd7070Spatrick while (Mod->Parent) {
5345e5dd7070Spatrick Mod = Mod->Parent;
5346e5dd7070Spatrick ++Result;
5347e5dd7070Spatrick }
5348e5dd7070Spatrick return Result;
5349e5dd7070Spatrick }
5350e5dd7070Spatrick
ImportDecl(DeclContext * DC,SourceLocation StartLoc,Module * Imported,ArrayRef<SourceLocation> IdentifierLocs)5351e5dd7070Spatrick ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
5352e5dd7070Spatrick Module *Imported,
5353e5dd7070Spatrick ArrayRef<SourceLocation> IdentifierLocs)
5354ec727ea7Spatrick : Decl(Import, DC, StartLoc), ImportedModule(Imported),
5355ec727ea7Spatrick NextLocalImportAndComplete(nullptr, true) {
5356e5dd7070Spatrick assert(getNumModuleIdentifiers(Imported) == IdentifierLocs.size());
5357e5dd7070Spatrick auto *StoredLocs = getTrailingObjects<SourceLocation>();
5358e5dd7070Spatrick std::uninitialized_copy(IdentifierLocs.begin(), IdentifierLocs.end(),
5359e5dd7070Spatrick StoredLocs);
5360e5dd7070Spatrick }
5361e5dd7070Spatrick
ImportDecl(DeclContext * DC,SourceLocation StartLoc,Module * Imported,SourceLocation EndLoc)5362e5dd7070Spatrick ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
5363e5dd7070Spatrick Module *Imported, SourceLocation EndLoc)
5364ec727ea7Spatrick : Decl(Import, DC, StartLoc), ImportedModule(Imported),
5365ec727ea7Spatrick NextLocalImportAndComplete(nullptr, false) {
5366e5dd7070Spatrick *getTrailingObjects<SourceLocation>() = EndLoc;
5367e5dd7070Spatrick }
5368e5dd7070Spatrick
Create(ASTContext & C,DeclContext * DC,SourceLocation StartLoc,Module * Imported,ArrayRef<SourceLocation> IdentifierLocs)5369e5dd7070Spatrick ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC,
5370e5dd7070Spatrick SourceLocation StartLoc, Module *Imported,
5371e5dd7070Spatrick ArrayRef<SourceLocation> IdentifierLocs) {
5372e5dd7070Spatrick return new (C, DC,
5373e5dd7070Spatrick additionalSizeToAlloc<SourceLocation>(IdentifierLocs.size()))
5374e5dd7070Spatrick ImportDecl(DC, StartLoc, Imported, IdentifierLocs);
5375e5dd7070Spatrick }
5376e5dd7070Spatrick
CreateImplicit(ASTContext & C,DeclContext * DC,SourceLocation StartLoc,Module * Imported,SourceLocation EndLoc)5377e5dd7070Spatrick ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC,
5378e5dd7070Spatrick SourceLocation StartLoc,
5379e5dd7070Spatrick Module *Imported,
5380e5dd7070Spatrick SourceLocation EndLoc) {
5381e5dd7070Spatrick ImportDecl *Import = new (C, DC, additionalSizeToAlloc<SourceLocation>(1))
5382e5dd7070Spatrick ImportDecl(DC, StartLoc, Imported, EndLoc);
5383e5dd7070Spatrick Import->setImplicit();
5384e5dd7070Spatrick return Import;
5385e5dd7070Spatrick }
5386e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID,unsigned NumLocations)5387e5dd7070Spatrick ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID,
5388e5dd7070Spatrick unsigned NumLocations) {
5389e5dd7070Spatrick return new (C, ID, additionalSizeToAlloc<SourceLocation>(NumLocations))
5390e5dd7070Spatrick ImportDecl(EmptyShell());
5391e5dd7070Spatrick }
5392e5dd7070Spatrick
getIdentifierLocs() const5393e5dd7070Spatrick ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const {
5394ec727ea7Spatrick if (!isImportComplete())
5395*12c85518Srobert return std::nullopt;
5396e5dd7070Spatrick
5397e5dd7070Spatrick const auto *StoredLocs = getTrailingObjects<SourceLocation>();
5398*12c85518Srobert return llvm::ArrayRef(StoredLocs,
5399e5dd7070Spatrick getNumModuleIdentifiers(getImportedModule()));
5400e5dd7070Spatrick }
5401e5dd7070Spatrick
getSourceRange() const5402e5dd7070Spatrick SourceRange ImportDecl::getSourceRange() const {
5403ec727ea7Spatrick if (!isImportComplete())
5404e5dd7070Spatrick return SourceRange(getLocation(), *getTrailingObjects<SourceLocation>());
5405e5dd7070Spatrick
5406e5dd7070Spatrick return SourceRange(getLocation(), getIdentifierLocs().back());
5407e5dd7070Spatrick }
5408e5dd7070Spatrick
5409e5dd7070Spatrick //===----------------------------------------------------------------------===//
5410e5dd7070Spatrick // ExportDecl Implementation
5411e5dd7070Spatrick //===----------------------------------------------------------------------===//
5412e5dd7070Spatrick
anchor()5413e5dd7070Spatrick void ExportDecl::anchor() {}
5414e5dd7070Spatrick
Create(ASTContext & C,DeclContext * DC,SourceLocation ExportLoc)5415e5dd7070Spatrick ExportDecl *ExportDecl::Create(ASTContext &C, DeclContext *DC,
5416e5dd7070Spatrick SourceLocation ExportLoc) {
5417e5dd7070Spatrick return new (C, DC) ExportDecl(DC, ExportLoc);
5418e5dd7070Spatrick }
5419e5dd7070Spatrick
CreateDeserialized(ASTContext & C,unsigned ID)5420e5dd7070Spatrick ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
5421e5dd7070Spatrick return new (C, ID) ExportDecl(nullptr, SourceLocation());
5422e5dd7070Spatrick }
5423