2017-11-15 07:13:32 +08:00
|
|
|
//===- DeclCXX.cpp - C++ Declaration AST Node Implementation --------------===//
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the C++ related Decl classes.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2017-11-15 07:13:32 +08:00
|
|
|
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
|
|
|
#include "clang/AST/ASTContext.h"
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
#include "clang/AST/ASTLambda.h"
|
2010-10-25 01:26:36 +08:00
|
|
|
#include "clang/AST/ASTMutationListener.h"
|
2017-11-15 07:13:32 +08:00
|
|
|
#include "clang/AST/ASTUnresolvedSet.h"
|
2019-11-16 09:31:55 +08:00
|
|
|
#include "clang/AST/Attr.h"
|
2010-09-29 08:15:42 +08:00
|
|
|
#include "clang/AST/CXXInheritance.h"
|
2017-11-15 07:13:32 +08:00
|
|
|
#include "clang/AST/DeclBase.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/AST/DeclTemplate.h"
|
2017-11-15 07:13:32 +08:00
|
|
|
#include "clang/AST/DeclarationName.h"
|
2009-03-14 08:25:26 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2011-11-01 09:16:03 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2017-11-15 07:13:32 +08:00
|
|
|
#include "clang/AST/LambdaCapture.h"
|
|
|
|
#include "clang/AST/NestedNameSpecifier.h"
|
2017-02-22 09:11:25 +08:00
|
|
|
#include "clang/AST/ODRHash.h"
|
2017-11-15 07:13:32 +08:00
|
|
|
#include "clang/AST/Type.h"
|
2009-12-03 06:36:29 +08:00
|
|
|
#include "clang/AST/TypeLoc.h"
|
2017-11-15 07:13:32 +08:00
|
|
|
#include "clang/AST/UnresolvedSet.h"
|
|
|
|
#include "clang/Basic/Diagnostic.h"
|
2008-11-13 07:21:09 +08:00
|
|
|
#include "clang/Basic/IdentifierTable.h"
|
2017-11-15 07:13:32 +08:00
|
|
|
#include "clang/Basic/LLVM.h"
|
|
|
|
#include "clang/Basic/LangOptions.h"
|
|
|
|
#include "clang/Basic/OperatorKinds.h"
|
|
|
|
#include "clang/Basic/PartialDiagnostic.h"
|
|
|
|
#include "clang/Basic/SourceLocation.h"
|
|
|
|
#include "clang/Basic/Specifiers.h"
|
|
|
|
#include "llvm/ADT/None.h"
|
2009-09-13 03:52:10 +08:00
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
2017-11-15 07:13:32 +08:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
|
|
#include "llvm/ADT/iterator_range.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
Rework how UuidAttr, CXXUuidofExpr, and GUID template arguments and constants are represented.
Summary:
Previously, we treated CXXUuidofExpr as quite a special case: it was the
only kind of expression that could be a canonical template argument, it
could be a constant lvalue base object, and so on. In addition, we
represented the UUID value as a string, whose source form we did not
preserve faithfully, and that we partially parsed in multiple different
places.
With this patch, we create an MSGuidDecl object to represent the
implicit object of type 'struct _GUID' created by a UuidAttr. Each
UuidAttr holds a pointer to its 'struct _GUID' and its original
(as-written) UUID string. A non-value-dependent CXXUuidofExpr behaves
like a DeclRefExpr denoting that MSGuidDecl object. We cache an APValue
representation of the GUID on the MSGuidDecl and use it from constant
evaluation where needed.
This allows removing a lot of the special-case logic to handle these
expressions. Unfortunately, many parts of Clang assume there are only
a couple of interesting kinds of ValueDecl, so the total amount of
special-case logic is not really reduced very much.
This fixes a few bugs and issues:
* PR38490: we now support reading from GUID objects returned from
__uuidof during constant evaluation.
* Our Itanium mangling for a non-instantiation-dependent template
argument involving __uuidof no longer depends on which CXXUuidofExpr
template argument we happened to see first.
* We now predeclare ::_GUID, and permit use of __uuidof without
any header inclusion, better matching MSVC's behavior. We do not
predefine ::__s_GUID, though; that seems like a step too far.
* Our IR representation for GUID constants now uses the correct IR type
wherever possible. We will still fall back to using the
{i32, i16, i16, [8 x i8]}
layout if a definition of struct _GUID is not available. This is not
ideal: in principle the two layouts could have different padding.
Reviewers: rnk, jdoerfert
Subscribers: arphaman, cfe-commits, aeubanks
Tags: #clang
Differential Revision: https://reviews.llvm.org/D78171
2020-04-12 13:15:29 +08:00
|
|
|
#include "llvm/Support/Format.h"
|
2017-11-15 07:13:32 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
|
|
|
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Decl Allocation/Deallocation Method Implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
2008-12-06 02:15:24 +08:00
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void AccessSpecDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, ID) AccessSpecDecl(EmptyShell());
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2013-08-30 12:46:40 +08:00
|
|
|
void LazyASTUnresolvedSet::getFromExternalSource(ASTContext &C) const {
|
|
|
|
ExternalASTSource *Source = C.getExternalSource();
|
|
|
|
assert(Impl.Decls.isLazy() && "getFromExternalSource for non-lazy set");
|
|
|
|
assert(Source && "getFromExternalSource with no external source");
|
|
|
|
|
|
|
|
for (ASTUnresolvedSet::iterator I = Impl.begin(); I != Impl.end(); ++I)
|
|
|
|
I.setDecl(cast<NamedDecl>(Source->GetExternalDecl(
|
|
|
|
reinterpret_cast<uintptr_t>(I.getDecl()) >> 2)));
|
|
|
|
Impl.Decls.setLazy(false);
|
|
|
|
}
|
|
|
|
|
2010-02-05 06:26:26 +08:00
|
|
|
CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
|
2016-02-19 09:52:46 +08:00
|
|
|
: UserDeclaredConstructor(false), UserDeclaredSpecialMembers(0),
|
|
|
|
Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
|
2018-04-06 02:55:37 +08:00
|
|
|
Abstract(false), IsStandardLayout(true), IsCXX11StandardLayout(true),
|
|
|
|
HasBasesWithFields(false), HasBasesWithNonStaticDataMembers(false),
|
2016-02-19 09:52:46 +08:00
|
|
|
HasPrivateFields(false), HasProtectedFields(false),
|
|
|
|
HasPublicFields(false), HasMutableFields(false), HasVariantMembers(false),
|
|
|
|
HasOnlyCMembers(true), HasInClassInitializer(false),
|
|
|
|
HasUninitializedReferenceMember(false), HasUninitializedFields(false),
|
2016-05-13 14:47:56 +08:00
|
|
|
HasInheritedConstructor(false), HasInheritedAssignment(false),
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
NeedOverloadResolutionForCopyConstructor(false),
|
2016-02-19 09:52:46 +08:00
|
|
|
NeedOverloadResolutionForMoveConstructor(false),
|
2020-06-05 10:16:05 +08:00
|
|
|
NeedOverloadResolutionForCopyAssignment(false),
|
2016-02-19 09:52:46 +08:00
|
|
|
NeedOverloadResolutionForMoveAssignment(false),
|
|
|
|
NeedOverloadResolutionForDestructor(false),
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
DefaultedCopyConstructorIsDeleted(false),
|
2016-02-19 09:52:46 +08:00
|
|
|
DefaultedMoveConstructorIsDeleted(false),
|
2020-06-05 10:16:05 +08:00
|
|
|
DefaultedCopyAssignmentIsDeleted(false),
|
2016-02-19 09:52:46 +08:00
|
|
|
DefaultedMoveAssignmentIsDeleted(false),
|
|
|
|
DefaultedDestructorIsDeleted(false), HasTrivialSpecialMembers(SMF_All),
|
2018-02-06 04:23:22 +08:00
|
|
|
HasTrivialSpecialMembersForCall(SMF_All),
|
|
|
|
DeclaredNonTrivialSpecialMembers(0),
|
|
|
|
DeclaredNonTrivialSpecialMembersForCall(0), HasIrrelevantDestructor(true),
|
2016-02-19 09:52:46 +08:00
|
|
|
HasConstexprNonCopyMoveConstructor(false),
|
2016-02-25 04:58:14 +08:00
|
|
|
HasDefaultedDefaultConstructor(false),
|
2016-02-19 09:52:46 +08:00
|
|
|
DefaultedDefaultConstructorIsConstexpr(true),
|
|
|
|
HasConstexprDefaultConstructor(false),
|
2019-09-23 11:48:44 +08:00
|
|
|
DefaultedDestructorIsConstexpr(true),
|
2020-09-21 11:10:02 +08:00
|
|
|
HasNonLiteralTypeFieldsOrBases(false), StructuralIfLiteral(true),
|
2016-02-19 09:52:46 +08:00
|
|
|
UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0),
|
C++ DR1611, 1658, 2180: implement "potentially constructed subobject" rules for special member functions.
Essentially, as a base class constructor does not construct virtual bases, such
a constructor for an abstract class does not need the corresponding base class
construction to be valid, and likewise for destructors.
This creates an awkward situation: clang will sometimes generate references to
the complete object and deleting destructors for an abstract class (it puts
them in the construction vtable for a derived class). But we can't generate a
"correct" version of these because we can't generate references to base class
constructors any more (if they're template specializations, say, we might not
have instantiated them and can't assume any other TU will emit a copy).
Fortunately, we don't need to, since no correct program can ever invoke them,
so instead emit symbols that just trap.
We should stop emitting references to these symbols, but still need to emit
definitions for compatibility.
llvm-svn: 296275
2017-02-26 07:53:05 +08:00
|
|
|
ImplicitCopyConstructorCanHaveConstParamForVBase(true),
|
|
|
|
ImplicitCopyConstructorCanHaveConstParamForNonVBase(true),
|
2016-02-19 09:52:46 +08:00
|
|
|
ImplicitCopyAssignmentHasConstParam(true),
|
|
|
|
HasDeclaredCopyConstructorWithConstParam(false),
|
|
|
|
HasDeclaredCopyAssignmentWithConstParam(false), IsLambda(false),
|
2019-10-11 08:29:04 +08:00
|
|
|
IsParsingBaseSpecifiers(false), ComputedVisibleConversions(false),
|
|
|
|
HasODRHash(false), Definition(D) {}
|
2010-02-05 06:26:26 +08:00
|
|
|
|
2012-07-05 01:03:33 +08:00
|
|
|
CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const {
|
|
|
|
return Bases.get(Definition->getASTContext().getExternalSource());
|
|
|
|
}
|
|
|
|
|
|
|
|
CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getVBasesSlowCase() const {
|
|
|
|
return VBases.get(Definition->getASTContext().getExternalSource());
|
|
|
|
}
|
|
|
|
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C,
|
|
|
|
DeclContext *DC, SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc, IdentifierInfo *Id,
|
|
|
|
CXXRecordDecl *PrevDecl)
|
|
|
|
: RecordDecl(K, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl),
|
|
|
|
DefinitionData(PrevDecl ? PrevDecl->DefinitionData
|
2017-11-15 07:13:32 +08:00
|
|
|
: nullptr) {}
|
2008-11-13 07:21:09 +08:00
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK,
|
2011-03-09 22:09:51 +08:00
|
|
|
DeclContext *DC, SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc, IdentifierInfo *Id,
|
2017-10-11 06:33:17 +08:00
|
|
|
CXXRecordDecl *PrevDecl,
|
2009-05-16 03:11:46 +08:00
|
|
|
bool DelayTypeCreation) {
|
2018-04-03 08:11:50 +08:00
|
|
|
auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, IdLoc, Id,
|
|
|
|
PrevDecl);
|
2018-08-02 04:48:16 +08:00
|
|
|
R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 07:36:44 +08:00
|
|
|
// FIXME: DelayTypeCreation seems like such a hack
|
2009-05-16 03:11:46 +08:00
|
|
|
if (!DelayTypeCreation)
|
2009-09-09 23:08:12 +08:00
|
|
|
C.getTypeDeclType(R, PrevDecl);
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
return R;
|
|
|
|
}
|
|
|
|
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
CXXRecordDecl *
|
|
|
|
CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
|
|
|
|
TypeSourceInfo *Info, SourceLocation Loc,
|
|
|
|
bool Dependent, bool IsGeneric,
|
|
|
|
LambdaCaptureDefault CaptureDefault) {
|
2018-04-03 08:11:50 +08:00
|
|
|
auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc,
|
|
|
|
nullptr, nullptr);
|
2018-08-02 04:48:16 +08:00
|
|
|
R->setBeingDefined(true);
|
2014-05-23 07:19:02 +08:00
|
|
|
R->DefinitionData =
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric,
|
2014-05-23 07:19:02 +08:00
|
|
|
CaptureDefault);
|
2018-08-02 04:48:16 +08:00
|
|
|
R->setMayHaveOutOfDateDef(false);
|
2013-09-06 01:46:21 +08:00
|
|
|
R->setImplicit(true);
|
2014-05-12 13:36:57 +08:00
|
|
|
C.getTypeDeclType(R, /*PrevDecl=*/nullptr);
|
2012-02-13 23:44:47 +08:00
|
|
|
return R;
|
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
CXXRecordDecl *
|
|
|
|
CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
|
2018-04-03 08:11:50 +08:00
|
|
|
auto *R = new (C, ID) CXXRecordDecl(
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
CXXRecord, TTK_Struct, C, nullptr, SourceLocation(), SourceLocation(),
|
2014-05-12 13:36:57 +08:00
|
|
|
nullptr, nullptr);
|
2018-08-02 04:48:16 +08:00
|
|
|
R->setMayHaveOutOfDateDef(false);
|
Ensure that type definitions present in just-loaded modules are
visible.
The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,
class X;
X *x;
and then import a module that includes a definition of X:
import XDef;
We will then fail when attempting to access a member of X, e.g.,
x->method()
because the AST reader did not know to look for a default of a class
named X within the new module.
This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.
In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,
// module 1
namespace N { struct X; }
// module 2
namespace N { struct X { /* ... */ }; }
One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.
llvm-svn: 174794
2013-02-09 09:35:03 +08:00
|
|
|
return R;
|
2010-07-02 19:54:55 +08:00
|
|
|
}
|
|
|
|
|
2018-04-06 02:55:37 +08:00
|
|
|
/// Determine whether a class has a repeated base class. This is intended for
|
|
|
|
/// use when determining if a class is standard-layout, so makes no attempt to
|
|
|
|
/// handle virtual bases.
|
|
|
|
static bool hasRepeatedBaseClass(const CXXRecordDecl *StartRD) {
|
|
|
|
llvm::SmallPtrSet<const CXXRecordDecl*, 8> SeenBaseTypes;
|
|
|
|
SmallVector<const CXXRecordDecl*, 8> WorkList = {StartRD};
|
|
|
|
while (!WorkList.empty()) {
|
|
|
|
const CXXRecordDecl *RD = WorkList.pop_back_val();
|
|
|
|
for (const CXXBaseSpecifier &BaseSpec : RD->bases()) {
|
|
|
|
if (const CXXRecordDecl *B = BaseSpec.getType()->getAsCXXRecordDecl()) {
|
|
|
|
if (!SeenBaseTypes.insert(B).second)
|
|
|
|
return true;
|
|
|
|
WorkList.push_back(B);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void
|
2015-12-25 08:36:02 +08:00
|
|
|
CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
|
|
|
|
unsigned NumBases) {
|
2010-02-11 09:30:34 +08:00
|
|
|
ASTContext &C = getASTContext();
|
2008-11-06 00:20:31 +08:00
|
|
|
|
2010-10-30 06:39:52 +08:00
|
|
|
if (!data().Bases.isOffset() && data().NumBases > 0)
|
|
|
|
C.Deallocate(data().getBases());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2015-12-25 08:36:02 +08:00
|
|
|
if (NumBases) {
|
2017-12-05 04:27:34 +08:00
|
|
|
if (!C.getLangOpts().CPlusPlus17) {
|
2016-03-09 06:17:41 +08:00
|
|
|
// C++ [dcl.init.aggr]p1:
|
|
|
|
// An aggregate is [...] a class with [...] no base classes [...].
|
|
|
|
data().Aggregate = false;
|
|
|
|
}
|
2011-10-19 04:08:55 +08:00
|
|
|
|
|
|
|
// C++ [class]p4:
|
|
|
|
// A POD-struct is an aggregate class...
|
|
|
|
data().PlainOldData = false;
|
|
|
|
}
|
|
|
|
|
2010-03-29 13:13:12 +08:00
|
|
|
// The set of seen virtual base types.
|
2010-03-30 03:49:09 +08:00
|
|
|
llvm::SmallPtrSet<CanQualType, 8> SeenVBaseTypes;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-03-29 13:13:12 +08:00
|
|
|
// The virtual bases of this class.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<const CXXBaseSpecifier *, 8> VBases;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2015-12-25 08:36:02 +08:00
|
|
|
data().Bases = new(C) CXXBaseSpecifier [NumBases];
|
|
|
|
data().NumBases = NumBases;
|
|
|
|
for (unsigned i = 0; i < NumBases; ++i) {
|
2010-10-30 06:39:52 +08:00
|
|
|
data().getBases()[i] = *Bases[i];
|
2009-07-11 04:13:23 +08:00
|
|
|
// Keep track of inherited vbases for this base class.
|
|
|
|
const CXXBaseSpecifier *Base = Bases[i];
|
|
|
|
QualType BaseType = Base->getType();
|
2010-02-27 08:25:28 +08:00
|
|
|
// Skip dependent types; we can't do any checking on them now.
|
2009-07-11 04:13:23 +08:00
|
|
|
if (BaseType->isDependentType())
|
|
|
|
continue;
|
2018-04-03 08:11:50 +08:00
|
|
|
auto *BaseClassDecl =
|
2019-10-03 19:22:48 +08:00
|
|
|
cast<CXXRecordDecl>(BaseType->castAs<RecordType>()->getDecl());
|
2010-03-29 13:13:12 +08:00
|
|
|
|
2018-04-06 02:55:37 +08:00
|
|
|
// C++2a [class]p7:
|
|
|
|
// A standard-layout class is a class that:
|
|
|
|
// [...]
|
|
|
|
// -- has all non-static data members and bit-fields in the class and
|
|
|
|
// its base classes first declared in the same class
|
|
|
|
if (BaseClassDecl->data().HasBasesWithFields ||
|
|
|
|
!BaseClassDecl->field_empty()) {
|
|
|
|
if (data().HasBasesWithFields)
|
|
|
|
// Two bases have members or bit-fields: not standard-layout.
|
2011-04-30 18:07:30 +08:00
|
|
|
data().IsStandardLayout = false;
|
2018-04-06 02:55:37 +08:00
|
|
|
data().HasBasesWithFields = true;
|
|
|
|
}
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
|
2018-04-06 02:55:37 +08:00
|
|
|
// C++11 [class]p7:
|
|
|
|
// A standard-layout class is a class that:
|
|
|
|
// -- [...] has [...] at most one base class with non-static data
|
|
|
|
// members
|
|
|
|
if (BaseClassDecl->data().HasBasesWithNonStaticDataMembers ||
|
|
|
|
BaseClassDecl->hasDirectFields()) {
|
|
|
|
if (data().HasBasesWithNonStaticDataMembers)
|
|
|
|
data().IsCXX11StandardLayout = false;
|
|
|
|
data().HasBasesWithNonStaticDataMembers = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!BaseClassDecl->isEmpty()) {
|
2016-05-22 13:34:26 +08:00
|
|
|
// C++14 [meta.unary.prop]p4:
|
|
|
|
// T is a class type [...] with [...] no base class B for which
|
|
|
|
// is_empty<B>::value is false.
|
2010-09-29 04:38:10 +08:00
|
|
|
data().Empty = false;
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
}
|
2018-04-06 02:55:37 +08:00
|
|
|
|
2016-03-09 06:17:41 +08:00
|
|
|
// C++1z [dcl.init.agg]p1:
|
|
|
|
// An aggregate is a class with [...] no private or protected base classes
|
2020-09-21 11:10:02 +08:00
|
|
|
if (Base->getAccessSpecifier() != AS_public) {
|
2016-03-09 06:17:41 +08:00
|
|
|
data().Aggregate = false;
|
|
|
|
|
2020-09-21 11:10:02 +08:00
|
|
|
// C++20 [temp.param]p7:
|
|
|
|
// A structural type is [...] a literal class type with [...] all base
|
|
|
|
// classes [...] public
|
|
|
|
data().StructuralIfLiteral = false;
|
|
|
|
}
|
|
|
|
|
2010-09-29 04:50:54 +08:00
|
|
|
// C++ [class.virtual]p1:
|
2018-07-31 03:24:48 +08:00
|
|
|
// A class that declares or inherits a virtual function is called a
|
2010-09-29 04:50:54 +08:00
|
|
|
// polymorphic class.
|
2018-06-15 04:03:22 +08:00
|
|
|
if (BaseClassDecl->isPolymorphic()) {
|
2010-09-29 04:50:54 +08:00
|
|
|
data().Polymorphic = true;
|
2011-04-24 10:49:34 +08:00
|
|
|
|
2018-06-15 04:03:22 +08:00
|
|
|
// An aggregate is a class with [...] no virtual functions.
|
|
|
|
data().Aggregate = false;
|
|
|
|
}
|
|
|
|
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
// C++0x [class]p7:
|
|
|
|
// A standard-layout class is a class that: [...]
|
|
|
|
// -- has no non-standard-layout base classes
|
2011-04-30 18:07:30 +08:00
|
|
|
if (!BaseClassDecl->isStandardLayout())
|
|
|
|
data().IsStandardLayout = false;
|
2018-04-06 02:55:37 +08:00
|
|
|
if (!BaseClassDecl->isCXX11StandardLayout())
|
|
|
|
data().IsCXX11StandardLayout = false;
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
|
2011-04-24 10:49:34 +08:00
|
|
|
// Record if this base is the first non-literal field or base.
|
2013-04-22 23:31:51 +08:00
|
|
|
if (!hasNonLiteralTypeFieldsOrBases() && !BaseType->isLiteralType(C))
|
2011-04-24 10:49:34 +08:00
|
|
|
data().HasNonLiteralTypeFieldsOrBases = true;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-03-29 13:13:12 +08:00
|
|
|
// Now go through all virtual bases of this base and add them.
|
2014-03-14 00:15:17 +08:00
|
|
|
for (const auto &VBase : BaseClassDecl->vbases()) {
|
2010-03-29 13:13:12 +08:00
|
|
|
// Add this base if it's not already in the list.
|
2014-11-19 15:49:47 +08:00
|
|
|
if (SeenVBaseTypes.insert(C.getCanonicalType(VBase.getType())).second) {
|
2014-03-14 00:15:17 +08:00
|
|
|
VBases.push_back(&VBase);
|
2012-11-28 14:23:12 +08:00
|
|
|
|
|
|
|
// C++11 [class.copy]p8:
|
|
|
|
// The implicitly-declared copy constructor for a class X will have
|
|
|
|
// the form 'X::X(const X&)' if each [...] virtual base class B of X
|
|
|
|
// has a copy constructor whose first parameter is of type
|
|
|
|
// 'const B&' or 'const volatile B&' [...]
|
2014-03-14 00:15:17 +08:00
|
|
|
if (CXXRecordDecl *VBaseDecl = VBase.getType()->getAsCXXRecordDecl())
|
2012-11-28 14:23:12 +08:00
|
|
|
if (!VBaseDecl->hasCopyConstructorWithConstParam())
|
C++ DR1611, 1658, 2180: implement "potentially constructed subobject" rules for special member functions.
Essentially, as a base class constructor does not construct virtual bases, such
a constructor for an abstract class does not need the corresponding base class
construction to be valid, and likewise for destructors.
This creates an awkward situation: clang will sometimes generate references to
the complete object and deleting destructors for an abstract class (it puts
them in the construction vtable for a derived class). But we can't generate a
"correct" version of these because we can't generate references to base class
constructors any more (if they're template specializations, say, we might not
have instantiated them and can't assume any other TU will emit a copy).
Fortunately, we don't need to, since no correct program can ever invoke them,
so instead emit symbols that just trap.
We should stop emitting references to these symbols, but still need to emit
definitions for compatibility.
llvm-svn: 296275
2017-02-26 07:53:05 +08:00
|
|
|
data().ImplicitCopyConstructorCanHaveConstParamForVBase = false;
|
2016-03-09 06:17:41 +08:00
|
|
|
|
|
|
|
// C++1z [dcl.init.agg]p1:
|
|
|
|
// An aggregate is a class with [...] no virtual base classes
|
|
|
|
data().Aggregate = false;
|
2012-11-28 14:23:12 +08:00
|
|
|
}
|
2009-07-11 04:13:23 +08:00
|
|
|
}
|
2010-03-29 13:13:12 +08:00
|
|
|
|
|
|
|
if (Base->isVirtual()) {
|
|
|
|
// Add this base if it's not already in the list.
|
2014-11-19 15:49:47 +08:00
|
|
|
if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType)).second)
|
2012-11-28 14:23:12 +08:00
|
|
|
VBases.push_back(Base);
|
|
|
|
|
2016-05-22 13:34:26 +08:00
|
|
|
// C++14 [meta.unary.prop] is_empty:
|
|
|
|
// T is a class type, but not a union type, with ... no virtual base
|
|
|
|
// classes
|
2010-09-29 04:38:10 +08:00
|
|
|
data().Empty = false;
|
2011-04-24 07:10:33 +08:00
|
|
|
|
2016-03-09 06:17:41 +08:00
|
|
|
// C++1z [dcl.init.agg]p1:
|
|
|
|
// An aggregate is a class with [...] no virtual base classes
|
|
|
|
data().Aggregate = false;
|
|
|
|
|
2012-11-30 13:11:39 +08:00
|
|
|
// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25:
|
|
|
|
// A [default constructor, copy/move constructor, or copy/move assignment
|
|
|
|
// operator for a class X] is trivial [...] if:
|
|
|
|
// -- class X has [...] no virtual base classes
|
|
|
|
data().HasTrivialSpecialMembers &= SMF_Destructor;
|
2018-02-06 04:23:22 +08:00
|
|
|
data().HasTrivialSpecialMembersForCall &= SMF_Destructor;
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
|
|
|
|
// C++0x [class]p7:
|
|
|
|
// A standard-layout class is a class that: [...]
|
|
|
|
// -- has [...] no virtual base classes
|
2011-04-30 18:07:30 +08:00
|
|
|
data().IsStandardLayout = false;
|
2018-04-06 02:55:37 +08:00
|
|
|
data().IsCXX11StandardLayout = false;
|
2011-12-22 10:22:31 +08:00
|
|
|
|
2019-09-23 11:48:44 +08:00
|
|
|
// C++20 [dcl.constexpr]p3:
|
|
|
|
// In the definition of a constexpr function [...]
|
|
|
|
// -- if the function is a constructor or destructor,
|
|
|
|
// its class shall not have any virtual base classes
|
2011-12-22 10:22:31 +08:00
|
|
|
data().DefaultedDefaultConstructorIsConstexpr = false;
|
2019-09-23 11:48:44 +08:00
|
|
|
data().DefaultedDestructorIsConstexpr = false;
|
C++ DR1611, 1658, 2180: implement "potentially constructed subobject" rules for special member functions.
Essentially, as a base class constructor does not construct virtual bases, such
a constructor for an abstract class does not need the corresponding base class
construction to be valid, and likewise for destructors.
This creates an awkward situation: clang will sometimes generate references to
the complete object and deleting destructors for an abstract class (it puts
them in the construction vtable for a derived class). But we can't generate a
"correct" version of these because we can't generate references to base class
constructors any more (if they're template specializations, say, we might not
have instantiated them and can't assume any other TU will emit a copy).
Fortunately, we don't need to, since no correct program can ever invoke them,
so instead emit symbols that just trap.
We should stop emitting references to these symbols, but still need to emit
definitions for compatibility.
llvm-svn: 296275
2017-02-26 07:53:05 +08:00
|
|
|
|
|
|
|
// C++1z [class.copy]p8:
|
|
|
|
// The implicitly-declared copy constructor for a class X will have
|
|
|
|
// the form 'X::X(const X&)' if each potentially constructed subobject
|
|
|
|
// has a copy constructor whose first parameter is of type
|
|
|
|
// 'const B&' or 'const volatile B&' [...]
|
|
|
|
if (!BaseClassDecl->hasCopyConstructorWithConstParam())
|
|
|
|
data().ImplicitCopyConstructorCanHaveConstParamForVBase = false;
|
2010-09-29 04:50:54 +08:00
|
|
|
} else {
|
|
|
|
// C++ [class.ctor]p5:
|
2011-05-10 02:22:59 +08:00
|
|
|
// A default constructor is trivial [...] if:
|
|
|
|
// -- all the direct base classes of its class have trivial default
|
|
|
|
// constructors.
|
|
|
|
if (!BaseClassDecl->hasTrivialDefaultConstructor())
|
2012-11-30 13:11:39 +08:00
|
|
|
data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor;
|
|
|
|
|
2011-04-24 07:10:33 +08:00
|
|
|
// C++0x [class.copy]p13:
|
|
|
|
// A copy/move constructor for class X is trivial if [...]
|
|
|
|
// [...]
|
|
|
|
// -- the constructor selected to copy/move each direct base class
|
|
|
|
// subobject is trivial, and
|
2010-09-29 04:50:54 +08:00
|
|
|
if (!BaseClassDecl->hasTrivialCopyConstructor())
|
2012-11-30 13:11:39 +08:00
|
|
|
data().HasTrivialSpecialMembers &= ~SMF_CopyConstructor;
|
2018-02-06 04:23:22 +08:00
|
|
|
|
|
|
|
if (!BaseClassDecl->hasTrivialCopyConstructorForCall())
|
|
|
|
data().HasTrivialSpecialMembersForCall &= ~SMF_CopyConstructor;
|
|
|
|
|
2012-12-08 16:32:28 +08:00
|
|
|
// If the base class doesn't have a simple move constructor, we'll eagerly
|
|
|
|
// declare it and perform overload resolution to determine which function
|
|
|
|
// it actually calls. If it does have a simple move constructor, this
|
|
|
|
// check is correct.
|
2012-11-16 08:53:38 +08:00
|
|
|
if (!BaseClassDecl->hasTrivialMoveConstructor())
|
2012-11-30 13:11:39 +08:00
|
|
|
data().HasTrivialSpecialMembers &= ~SMF_MoveConstructor;
|
2011-04-24 07:10:33 +08:00
|
|
|
|
2018-02-06 04:23:22 +08:00
|
|
|
if (!BaseClassDecl->hasTrivialMoveConstructorForCall())
|
|
|
|
data().HasTrivialSpecialMembersForCall &= ~SMF_MoveConstructor;
|
|
|
|
|
2011-04-24 07:10:33 +08:00
|
|
|
// C++0x [class.copy]p27:
|
|
|
|
// A copy/move assignment operator for class X is trivial if [...]
|
|
|
|
// [...]
|
|
|
|
// -- the assignment operator selected to copy/move each direct base
|
|
|
|
// class subobject is trivial, and
|
2010-09-29 04:50:54 +08:00
|
|
|
if (!BaseClassDecl->hasTrivialCopyAssignment())
|
2012-11-30 13:11:39 +08:00
|
|
|
data().HasTrivialSpecialMembers &= ~SMF_CopyAssignment;
|
2012-12-08 16:32:28 +08:00
|
|
|
// If the base class doesn't have a simple move assignment, we'll eagerly
|
|
|
|
// declare it and perform overload resolution to determine which function
|
|
|
|
// it actually calls. If it does have a simple move assignment, this
|
|
|
|
// check is correct.
|
2012-11-16 08:53:38 +08:00
|
|
|
if (!BaseClassDecl->hasTrivialMoveAssignment())
|
2012-11-30 13:11:39 +08:00
|
|
|
data().HasTrivialSpecialMembers &= ~SMF_MoveAssignment;
|
2011-12-22 10:22:31 +08:00
|
|
|
|
|
|
|
// C++11 [class.ctor]p6:
|
2012-01-12 02:26:05 +08:00
|
|
|
// If that user-written default constructor would satisfy the
|
2011-12-22 10:22:31 +08:00
|
|
|
// requirements of a constexpr constructor, the implicitly-defined
|
|
|
|
// default constructor is constexpr.
|
|
|
|
if (!BaseClassDecl->hasConstexprDefaultConstructor())
|
|
|
|
data().DefaultedDefaultConstructorIsConstexpr = false;
|
C++ DR1611, 1658, 2180: implement "potentially constructed subobject" rules for special member functions.
Essentially, as a base class constructor does not construct virtual bases, such
a constructor for an abstract class does not need the corresponding base class
construction to be valid, and likewise for destructors.
This creates an awkward situation: clang will sometimes generate references to
the complete object and deleting destructors for an abstract class (it puts
them in the construction vtable for a derived class). But we can't generate a
"correct" version of these because we can't generate references to base class
constructors any more (if they're template specializations, say, we might not
have instantiated them and can't assume any other TU will emit a copy).
Fortunately, we don't need to, since no correct program can ever invoke them,
so instead emit symbols that just trap.
We should stop emitting references to these symbols, but still need to emit
definitions for compatibility.
llvm-svn: 296275
2017-02-26 07:53:05 +08:00
|
|
|
|
|
|
|
// C++1z [class.copy]p8:
|
|
|
|
// The implicitly-declared copy constructor for a class X will have
|
|
|
|
// the form 'X::X(const X&)' if each potentially constructed subobject
|
|
|
|
// has a copy constructor whose first parameter is of type
|
|
|
|
// 'const B&' or 'const volatile B&' [...]
|
|
|
|
if (!BaseClassDecl->hasCopyConstructorWithConstParam())
|
|
|
|
data().ImplicitCopyConstructorCanHaveConstParamForNonVBase = false;
|
2009-07-11 04:13:23 +08:00
|
|
|
}
|
2012-12-08 10:53:02 +08:00
|
|
|
|
2010-09-29 04:50:54 +08:00
|
|
|
// C++ [class.ctor]p3:
|
|
|
|
// A destructor is trivial if all the direct base classes of its class
|
|
|
|
// have trivial destructors.
|
|
|
|
if (!BaseClassDecl->hasTrivialDestructor())
|
2012-11-30 13:11:39 +08:00
|
|
|
data().HasTrivialSpecialMembers &= ~SMF_Destructor;
|
2012-02-25 15:33:38 +08:00
|
|
|
|
2018-02-06 04:23:22 +08:00
|
|
|
if (!BaseClassDecl->hasTrivialDestructorForCall())
|
|
|
|
data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;
|
|
|
|
|
2012-02-25 15:33:38 +08:00
|
|
|
if (!BaseClassDecl->hasIrrelevantDestructor())
|
|
|
|
data().HasIrrelevantDestructor = false;
|
|
|
|
|
2012-11-28 14:23:12 +08:00
|
|
|
// C++11 [class.copy]p18:
|
2019-11-05 05:27:53 +08:00
|
|
|
// The implicitly-declared copy assignment operator for a class X will
|
2012-11-28 14:23:12 +08:00
|
|
|
// have the form 'X& X::operator=(const X&)' if each direct base class B
|
|
|
|
// of X has a copy assignment operator whose parameter is of type 'const
|
|
|
|
// B&', 'const volatile B&', or 'B' [...]
|
|
|
|
if (!BaseClassDecl->hasCopyAssignmentWithConstParam())
|
|
|
|
data().ImplicitCopyAssignmentHasConstParam = false;
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
// A class has an Objective-C object member if... or any of its bases
|
|
|
|
// has an Objective-C object member.
|
|
|
|
if (BaseClassDecl->hasObjectMember())
|
|
|
|
setHasObjectMember(true);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2013-01-26 07:57:05 +08:00
|
|
|
if (BaseClassDecl->hasVolatileMember())
|
|
|
|
setHasVolatileMember(true);
|
2011-06-16 07:02:42 +08:00
|
|
|
|
2018-04-10 06:48:22 +08:00
|
|
|
if (BaseClassDecl->getArgPassingRestrictions() ==
|
|
|
|
RecordDecl::APK_CanNeverPassInRegs)
|
|
|
|
setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
|
|
|
|
|
2011-05-13 09:05:07 +08:00
|
|
|
// Keep track of the presence of mutable fields.
|
2020-06-05 10:16:05 +08:00
|
|
|
if (BaseClassDecl->hasMutableFields())
|
2011-05-13 09:05:07 +08:00
|
|
|
data().HasMutableFields = true;
|
2012-12-08 10:01:17 +08:00
|
|
|
|
|
|
|
if (BaseClassDecl->hasUninitializedReferenceMember())
|
|
|
|
data().HasUninitializedReferenceMember = true;
|
2012-12-08 16:32:28 +08:00
|
|
|
|
2016-02-19 09:52:46 +08:00
|
|
|
if (!BaseClassDecl->allowConstDefaultInit())
|
|
|
|
data().HasUninitializedFields = true;
|
|
|
|
|
2012-12-08 16:32:28 +08:00
|
|
|
addedClassSubobject(BaseClassDecl);
|
2009-07-11 04:13:23 +08:00
|
|
|
}
|
2018-04-06 02:55:37 +08:00
|
|
|
|
|
|
|
// C++2a [class]p7:
|
|
|
|
// A class S is a standard-layout class if it:
|
|
|
|
// -- has at most one base class subobject of any given type
|
|
|
|
//
|
|
|
|
// Note that we only need to check this for classes with more than one base
|
|
|
|
// class. If there's only one base class, and it's standard layout, then
|
|
|
|
// we know there are no repeated base classes.
|
|
|
|
if (data().IsStandardLayout && NumBases > 1 && hasRepeatedBaseClass(this))
|
|
|
|
data().IsStandardLayout = false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2014-06-13 14:43:46 +08:00
|
|
|
if (VBases.empty()) {
|
|
|
|
data().IsParsingBaseSpecifiers = false;
|
2010-03-29 13:13:12 +08:00
|
|
|
return;
|
2014-06-13 14:43:46 +08:00
|
|
|
}
|
2010-03-29 13:13:12 +08:00
|
|
|
|
|
|
|
// Create base specifier for any direct or indirect virtual bases.
|
|
|
|
data().VBases = new (C) CXXBaseSpecifier[VBases.size()];
|
|
|
|
data().NumVBases = VBases.size();
|
2012-12-08 16:32:28 +08:00
|
|
|
for (int I = 0, E = VBases.size(); I != E; ++I) {
|
|
|
|
QualType Type = VBases[I]->getType();
|
|
|
|
if (!Type->isDependentType())
|
|
|
|
addedClassSubobject(Type->getAsCXXRecordDecl());
|
2011-07-13 07:49:11 +08:00
|
|
|
data().getVBases()[I] = *VBases[I];
|
2012-12-08 16:32:28 +08:00
|
|
|
}
|
2014-06-13 14:43:46 +08:00
|
|
|
|
|
|
|
data().IsParsingBaseSpecifiers = false;
|
2012-12-08 16:32:28 +08:00
|
|
|
}
|
|
|
|
|
2017-04-12 05:31:00 +08:00
|
|
|
unsigned CXXRecordDecl::getODRHash() const {
|
|
|
|
assert(hasDefinition() && "ODRHash only for records with definitions");
|
2017-02-22 09:11:25 +08:00
|
|
|
|
2017-04-12 05:31:00 +08:00
|
|
|
// Previously calculated hash is stored in DefinitionData.
|
|
|
|
if (DefinitionData->HasODRHash)
|
|
|
|
return DefinitionData->ODRHash;
|
2017-02-22 09:11:25 +08:00
|
|
|
|
2017-04-12 05:31:00 +08:00
|
|
|
// Only calculate hash on first call of getODRHash per record.
|
|
|
|
ODRHash Hash;
|
|
|
|
Hash.AddCXXRecordDecl(getDefinition());
|
|
|
|
DefinitionData->HasODRHash = true;
|
2017-02-22 09:11:25 +08:00
|
|
|
DefinitionData->ODRHash = Hash.CalculateHash();
|
2017-04-12 05:31:00 +08:00
|
|
|
|
|
|
|
return DefinitionData->ODRHash;
|
2017-02-22 09:11:25 +08:00
|
|
|
}
|
2017-02-18 10:09:28 +08:00
|
|
|
|
2012-12-08 16:32:28 +08:00
|
|
|
void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
|
|
|
|
// C++11 [class.copy]p11:
|
|
|
|
// A defaulted copy/move constructor for a class X is defined as
|
|
|
|
// deleted if X has:
|
|
|
|
// -- a direct or virtual base class B that cannot be copied/moved [...]
|
|
|
|
// -- a non-static data member of class type M (or array thereof)
|
|
|
|
// that cannot be copied or moved [...]
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
if (!Subobj->hasSimpleCopyConstructor())
|
|
|
|
data().NeedOverloadResolutionForCopyConstructor = true;
|
2012-12-08 16:32:28 +08:00
|
|
|
if (!Subobj->hasSimpleMoveConstructor())
|
|
|
|
data().NeedOverloadResolutionForMoveConstructor = true;
|
|
|
|
|
|
|
|
// C++11 [class.copy]p23:
|
|
|
|
// A defaulted copy/move assignment operator for a class X is defined as
|
|
|
|
// deleted if X has:
|
|
|
|
// -- a direct or virtual base class B that cannot be copied/moved [...]
|
|
|
|
// -- a non-static data member of class type M (or array thereof)
|
|
|
|
// that cannot be copied or moved [...]
|
2020-06-05 10:16:05 +08:00
|
|
|
if (!Subobj->hasSimpleCopyAssignment())
|
|
|
|
data().NeedOverloadResolutionForCopyAssignment = true;
|
2012-12-08 16:32:28 +08:00
|
|
|
if (!Subobj->hasSimpleMoveAssignment())
|
|
|
|
data().NeedOverloadResolutionForMoveAssignment = true;
|
|
|
|
|
|
|
|
// C++11 [class.ctor]p5, C++11 [class.copy]p11, C++11 [class.dtor]p5:
|
|
|
|
// A defaulted [ctor or dtor] for a class X is defined as
|
|
|
|
// deleted if X has:
|
|
|
|
// -- any direct or virtual base class [...] has a type with a destructor
|
|
|
|
// that is deleted or inaccessible from the defaulted [ctor or dtor].
|
|
|
|
// -- any non-static data member has a type with a destructor
|
|
|
|
// that is deleted or inaccessible from the defaulted [ctor or dtor].
|
|
|
|
if (!Subobj->hasSimpleDestructor()) {
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
data().NeedOverloadResolutionForCopyConstructor = true;
|
2012-12-08 16:32:28 +08:00
|
|
|
data().NeedOverloadResolutionForMoveConstructor = true;
|
|
|
|
data().NeedOverloadResolutionForDestructor = true;
|
|
|
|
}
|
2019-09-23 11:48:44 +08:00
|
|
|
|
|
|
|
// C++2a [dcl.constexpr]p4:
|
|
|
|
// The definition of a constexpr destructor [shall] satisfy the
|
|
|
|
// following requirement:
|
|
|
|
// -- for every subobject of class type or (possibly multi-dimensional)
|
|
|
|
// array thereof, that class type shall have a constexpr destructor
|
|
|
|
if (!Subobj->hasConstexprDestructor())
|
|
|
|
data().DefaultedDestructorIsConstexpr = false;
|
2020-09-21 11:10:02 +08:00
|
|
|
|
|
|
|
// C++20 [temp.param]p7:
|
|
|
|
// A structural type is [...] a literal class type [for which] the types
|
|
|
|
// of all base classes and non-static data members are structural types or
|
|
|
|
// (possibly multi-dimensional) array thereof
|
|
|
|
if (!Subobj->data().StructuralIfLiteral)
|
|
|
|
data().StructuralIfLiteral = false;
|
2019-09-23 11:48:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CXXRecordDecl::hasConstexprDestructor() const {
|
|
|
|
auto *Dtor = getDestructor();
|
|
|
|
return Dtor ? Dtor->isConstexpr() : defaultedDestructorIsConstexpr();
|
2008-10-24 02:13:27 +08:00
|
|
|
}
|
|
|
|
|
2010-01-15 01:47:39 +08:00
|
|
|
bool CXXRecordDecl::hasAnyDependentBases() const {
|
|
|
|
if (!isDependentContext())
|
|
|
|
return false;
|
|
|
|
|
2015-07-25 23:07:25 +08:00
|
|
|
return !forallBases([](const CXXRecordDecl *) { return true; });
|
2010-01-15 01:47:39 +08:00
|
|
|
}
|
|
|
|
|
2011-04-23 18:47:28 +08:00
|
|
|
bool CXXRecordDecl::isTriviallyCopyable() const {
|
|
|
|
// C++0x [class]p5:
|
|
|
|
// A trivially copyable class is a class that:
|
|
|
|
// -- has no non-trivial copy constructors,
|
2012-11-16 08:53:38 +08:00
|
|
|
if (hasNonTrivialCopyConstructor()) return false;
|
2011-04-23 18:47:28 +08:00
|
|
|
// -- has no non-trivial move constructors,
|
2012-11-16 08:53:38 +08:00
|
|
|
if (hasNonTrivialMoveConstructor()) return false;
|
2011-04-23 18:47:28 +08:00
|
|
|
// -- has no non-trivial copy assignment operators,
|
2012-11-16 08:53:38 +08:00
|
|
|
if (hasNonTrivialCopyAssignment()) return false;
|
2011-04-23 18:47:28 +08:00
|
|
|
// -- has no non-trivial move assignment operators, and
|
2012-11-16 08:53:38 +08:00
|
|
|
if (hasNonTrivialMoveAssignment()) return false;
|
2011-04-23 18:47:28 +08:00
|
|
|
// -- has a trivial destructor.
|
|
|
|
if (!hasTrivialDestructor()) return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-09-29 05:55:22 +08:00
|
|
|
void CXXRecordDecl::markedVirtualFunctionPure() {
|
2018-07-31 03:24:48 +08:00
|
|
|
// C++ [class.abstract]p2:
|
2010-09-29 05:55:22 +08:00
|
|
|
// A class is abstract if it has at least one pure virtual function.
|
|
|
|
data().Abstract = true;
|
|
|
|
}
|
|
|
|
|
2018-04-06 02:55:37 +08:00
|
|
|
bool CXXRecordDecl::hasSubobjectAtOffsetZeroOfEmptyBaseType(
|
|
|
|
ASTContext &Ctx, const CXXRecordDecl *XFirst) {
|
|
|
|
if (!getNumBases())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
llvm::SmallPtrSet<const CXXRecordDecl*, 8> Bases;
|
|
|
|
llvm::SmallPtrSet<const CXXRecordDecl*, 8> M;
|
|
|
|
SmallVector<const CXXRecordDecl*, 8> WorkList;
|
|
|
|
|
|
|
|
// Visit a type that we have determined is an element of M(S).
|
|
|
|
auto Visit = [&](const CXXRecordDecl *RD) -> bool {
|
|
|
|
RD = RD->getCanonicalDecl();
|
|
|
|
|
|
|
|
// C++2a [class]p8:
|
|
|
|
// A class S is a standard-layout class if it [...] has no element of the
|
|
|
|
// set M(S) of types as a base class.
|
|
|
|
//
|
|
|
|
// If we find a subobject of an empty type, it might also be a base class,
|
|
|
|
// so we'll need to walk the base classes to check.
|
|
|
|
if (!RD->data().HasBasesWithFields) {
|
|
|
|
// Walk the bases the first time, stopping if we find the type. Build a
|
|
|
|
// set of them so we don't need to walk them again.
|
|
|
|
if (Bases.empty()) {
|
|
|
|
bool RDIsBase = !forallBases([&](const CXXRecordDecl *Base) -> bool {
|
|
|
|
Base = Base->getCanonicalDecl();
|
|
|
|
if (RD == Base)
|
|
|
|
return false;
|
|
|
|
Bases.insert(Base);
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
if (RDIsBase)
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
if (Bases.count(RD))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (M.insert(RD).second)
|
|
|
|
WorkList.push_back(RD);
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (Visit(XFirst))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
while (!WorkList.empty()) {
|
|
|
|
const CXXRecordDecl *X = WorkList.pop_back_val();
|
|
|
|
|
|
|
|
// FIXME: We don't check the bases of X. That matches the standard, but
|
|
|
|
// that sure looks like a wording bug.
|
|
|
|
|
|
|
|
// -- If X is a non-union class type with a non-static data member
|
2019-06-21 04:44:45 +08:00
|
|
|
// [recurse to each field] that is either of zero size or is the
|
|
|
|
// first non-static data member of X
|
2018-04-06 02:55:37 +08:00
|
|
|
// -- If X is a union type, [recurse to union members]
|
2019-06-21 04:44:45 +08:00
|
|
|
bool IsFirstField = true;
|
2018-04-06 02:55:37 +08:00
|
|
|
for (auto *FD : X->fields()) {
|
|
|
|
// FIXME: Should we really care about the type of the first non-static
|
|
|
|
// data member of a non-union if there are preceding unnamed bit-fields?
|
|
|
|
if (FD->isUnnamedBitfield())
|
|
|
|
continue;
|
|
|
|
|
2019-06-21 04:44:45 +08:00
|
|
|
if (!IsFirstField && !FD->isZeroSize(Ctx))
|
|
|
|
continue;
|
|
|
|
|
2018-04-06 02:55:37 +08:00
|
|
|
// -- If X is n array type, [visit the element type]
|
|
|
|
QualType T = Ctx.getBaseElementType(FD->getType());
|
|
|
|
if (auto *RD = T->getAsCXXRecordDecl())
|
|
|
|
if (Visit(RD))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (!X->isUnion())
|
2019-06-21 04:44:45 +08:00
|
|
|
IsFirstField = false;
|
2018-04-06 02:55:37 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-09-28 06:47:04 +08:00
|
|
|
bool CXXRecordDecl::lambdaIsDefaultConstructibleAndAssignable() const {
|
|
|
|
assert(isLambda() && "not a lambda");
|
|
|
|
|
|
|
|
// C++2a [expr.prim.lambda.capture]p11:
|
|
|
|
// The closure type associated with a lambda-expression has no default
|
|
|
|
// constructor if the lambda-expression has a lambda-capture and a
|
|
|
|
// defaulted default constructor otherwise. It has a deleted copy
|
|
|
|
// assignment operator if the lambda-expression has a lambda-capture and
|
|
|
|
// defaulted copy and move assignment operators otherwise.
|
|
|
|
//
|
|
|
|
// C++17 [expr.prim.lambda]p21:
|
|
|
|
// The closure type associated with a lambda-expression has no default
|
|
|
|
// constructor and a deleted copy assignment operator.
|
2020-06-05 10:15:22 +08:00
|
|
|
if (getLambdaCaptureDefault() != LCD_None || capture_size() != 0)
|
2018-09-28 06:47:04 +08:00
|
|
|
return false;
|
2020-04-22 03:37:19 +08:00
|
|
|
return getASTContext().getLangOpts().CPlusPlus20;
|
2018-09-28 06:47:04 +08:00
|
|
|
}
|
|
|
|
|
2010-09-29 05:55:22 +08:00
|
|
|
void CXXRecordDecl::addedMember(Decl *D) {
|
2012-09-01 06:18:20 +08:00
|
|
|
if (!D->isImplicit() &&
|
|
|
|
!isa<FieldDecl>(D) &&
|
|
|
|
!isa<IndirectFieldDecl>(D) &&
|
|
|
|
(!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class ||
|
|
|
|
cast<TagDecl>(D)->getTagKind() == TTK_Interface))
|
|
|
|
data().HasOnlyCMembers = false;
|
|
|
|
|
|
|
|
// Ignore friends and invalid declarations.
|
2010-09-28 06:06:20 +08:00
|
|
|
if (D->getFriendObjectKind() || D->isInvalidDecl())
|
2010-09-28 05:17:54 +08:00
|
|
|
return;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2018-04-03 08:11:50 +08:00
|
|
|
auto *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
|
2010-09-28 06:06:20 +08:00
|
|
|
if (FunTmpl)
|
|
|
|
D = FunTmpl->getTemplatedDecl();
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
|
|
|
|
// FIXME: Pass NamedDecl* to addedMember?
|
|
|
|
Decl *DUnderlying = D;
|
|
|
|
if (auto *ND = dyn_cast<NamedDecl>(DUnderlying)) {
|
|
|
|
DUnderlying = ND->getUnderlyingDecl();
|
2018-04-03 08:11:50 +08:00
|
|
|
if (auto *UnderlyingFunTmpl = dyn_cast<FunctionTemplateDecl>(DUnderlying))
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
DUnderlying = UnderlyingFunTmpl->getTemplatedDecl();
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) {
|
2010-09-29 03:45:33 +08:00
|
|
|
if (Method->isVirtual()) {
|
|
|
|
// C++ [dcl.init.aggr]p1:
|
|
|
|
// An aggregate is an array or a class with [...] no virtual functions.
|
|
|
|
data().Aggregate = false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-09-29 03:45:33 +08:00
|
|
|
// C++ [class]p4:
|
|
|
|
// A POD-struct is an aggregate class...
|
|
|
|
data().PlainOldData = false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2016-05-22 13:34:26 +08:00
|
|
|
// C++14 [meta.unary.prop]p4:
|
|
|
|
// T is a class type [...] with [...] no virtual member functions...
|
2010-09-29 04:38:10 +08:00
|
|
|
data().Empty = false;
|
2010-09-29 04:50:54 +08:00
|
|
|
|
|
|
|
// C++ [class.virtual]p1:
|
2018-07-31 03:24:48 +08:00
|
|
|
// A class that declares or inherits a virtual function is called a
|
2010-09-29 04:50:54 +08:00
|
|
|
// polymorphic class.
|
|
|
|
data().Polymorphic = true;
|
2011-04-24 07:10:33 +08:00
|
|
|
|
2012-11-30 13:11:39 +08:00
|
|
|
// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25:
|
|
|
|
// A [default constructor, copy/move constructor, or copy/move
|
|
|
|
// assignment operator for a class X] is trivial [...] if:
|
2011-04-24 07:10:33 +08:00
|
|
|
// -- class X has no virtual functions [...]
|
2012-11-30 13:11:39 +08:00
|
|
|
data().HasTrivialSpecialMembers &= SMF_Destructor;
|
2018-02-06 04:23:22 +08:00
|
|
|
data().HasTrivialSpecialMembersForCall &= SMF_Destructor;
|
2011-04-24 07:10:33 +08:00
|
|
|
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
// C++0x [class]p7:
|
|
|
|
// A standard-layout class is a class that: [...]
|
|
|
|
// -- has no virtual functions
|
2011-04-30 18:07:30 +08:00
|
|
|
data().IsStandardLayout = false;
|
2018-04-06 02:55:37 +08:00
|
|
|
data().IsCXX11StandardLayout = false;
|
2010-09-29 03:45:33 +08:00
|
|
|
}
|
|
|
|
}
|
2010-09-29 04:38:10 +08:00
|
|
|
|
2012-11-28 14:23:12 +08:00
|
|
|
// Notify the listener if an implicit member was added after the definition
|
|
|
|
// was completed.
|
|
|
|
if (!isBeingDefined() && D->isImplicit())
|
|
|
|
if (ASTMutationListener *L = getASTMutationListener())
|
|
|
|
L->AddedCXXImplicitMember(data().Definition, D);
|
|
|
|
|
2012-11-30 13:11:39 +08:00
|
|
|
// The kind of special member this declaration is, if any.
|
|
|
|
unsigned SMKind = 0;
|
|
|
|
|
2012-11-28 14:23:12 +08:00
|
|
|
// Handle constructors.
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
|
2020-01-15 11:29:50 +08:00
|
|
|
if (Constructor->isInheritingConstructor()) {
|
|
|
|
// Ignore constructor shadow declarations. They are lazily created and
|
|
|
|
// so shouldn't affect any properties of the class.
|
|
|
|
} else {
|
|
|
|
if (!Constructor->isImplicit()) {
|
|
|
|
// Note that we have a user-declared constructor.
|
|
|
|
data().UserDeclaredConstructor = true;
|
|
|
|
|
|
|
|
// C++ [class]p4:
|
|
|
|
// A POD-struct is an aggregate class [...]
|
|
|
|
// Since the POD bit is meant to be C++03 POD-ness, clear it even if
|
|
|
|
// the type is technically an aggregate in C++0x since it wouldn't be
|
|
|
|
// in 03.
|
|
|
|
data().PlainOldData = false;
|
|
|
|
}
|
2012-11-28 14:23:12 +08:00
|
|
|
|
2020-01-15 11:29:50 +08:00
|
|
|
if (Constructor->isDefaultConstructor()) {
|
|
|
|
SMKind |= SMF_DefaultConstructor;
|
2009-06-18 06:44:31 +08:00
|
|
|
|
2020-01-15 11:29:50 +08:00
|
|
|
if (Constructor->isUserProvided())
|
|
|
|
data().UserProvidedDefaultConstructor = true;
|
|
|
|
if (Constructor->isConstexpr())
|
|
|
|
data().HasConstexprDefaultConstructor = true;
|
|
|
|
if (Constructor->isDefaulted())
|
|
|
|
data().HasDefaultedDefaultConstructor = true;
|
|
|
|
}
|
2012-11-30 13:11:39 +08:00
|
|
|
|
2020-01-15 11:29:50 +08:00
|
|
|
if (!FunTmpl) {
|
|
|
|
unsigned Quals;
|
|
|
|
if (Constructor->isCopyConstructor(Quals)) {
|
|
|
|
SMKind |= SMF_CopyConstructor;
|
2010-09-28 06:06:20 +08:00
|
|
|
|
2020-01-15 11:29:50 +08:00
|
|
|
if (Quals & Qualifiers::Const)
|
|
|
|
data().HasDeclaredCopyConstructorWithConstParam = true;
|
|
|
|
} else if (Constructor->isMoveConstructor())
|
|
|
|
SMKind |= SMF_MoveConstructor;
|
|
|
|
}
|
2012-11-28 14:23:12 +08:00
|
|
|
|
2020-01-15 11:29:50 +08:00
|
|
|
// C++11 [dcl.init.aggr]p1: DR1518
|
|
|
|
// An aggregate is an array or a class with no user-provided [or]
|
|
|
|
// explicit [...] constructors
|
|
|
|
// C++20 [dcl.init.aggr]p1:
|
|
|
|
// An aggregate is an array or a class with no user-declared [...]
|
|
|
|
// constructors
|
2020-04-22 03:37:19 +08:00
|
|
|
if (getASTContext().getLangOpts().CPlusPlus20
|
2020-01-15 11:29:50 +08:00
|
|
|
? !Constructor->isImplicit()
|
|
|
|
: (Constructor->isUserProvided() || Constructor->isExplicit()))
|
|
|
|
data().Aggregate = false;
|
2010-09-28 06:06:20 +08:00
|
|
|
}
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
}
|
2012-11-28 14:23:12 +08:00
|
|
|
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
// Handle constructors, including those inherited from base classes.
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(DUnderlying)) {
|
2012-11-28 14:23:12 +08:00
|
|
|
// Record if we see any constexpr constructors which are neither copy
|
|
|
|
// nor move constructors.
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
// C++1z [basic.types]p10:
|
|
|
|
// [...] has at least one constexpr constructor or constructor template
|
|
|
|
// (possibly inherited from a base class) that is not a copy or move
|
|
|
|
// constructor [...]
|
2012-11-28 14:23:12 +08:00
|
|
|
if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor())
|
2011-08-11 02:11:37 +08:00
|
|
|
data().HasConstexprNonCopyMoveConstructor = true;
|
2009-07-23 02:25:24 +08:00
|
|
|
}
|
2008-11-01 04:25:05 +08:00
|
|
|
|
2012-11-28 14:23:12 +08:00
|
|
|
// Handle destructors.
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *DD = dyn_cast<CXXDestructorDecl>(D)) {
|
2012-11-30 13:11:39 +08:00
|
|
|
SMKind |= SMF_Destructor;
|
2012-02-25 15:33:38 +08:00
|
|
|
|
2014-03-28 04:23:12 +08:00
|
|
|
if (DD->isUserProvided())
|
2012-11-28 14:23:12 +08:00
|
|
|
data().HasIrrelevantDestructor = false;
|
2014-03-28 04:23:12 +08:00
|
|
|
// If the destructor is explicitly defaulted and not trivial or not public
|
|
|
|
// or if the destructor is deleted, we clear HasIrrelevantDestructor in
|
|
|
|
// finishedDefaultedOrDeletedMember.
|
2012-11-28 14:23:12 +08:00
|
|
|
|
|
|
|
// C++11 [class.dtor]p5:
|
2012-11-30 13:11:39 +08:00
|
|
|
// A destructor is trivial if [...] the destructor is not virtual.
|
2018-02-06 04:23:22 +08:00
|
|
|
if (DD->isVirtual()) {
|
2012-11-30 13:11:39 +08:00
|
|
|
data().HasTrivialSpecialMembers &= ~SMF_Destructor;
|
2018-02-06 04:23:22 +08:00
|
|
|
data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;
|
|
|
|
}
|
2010-09-28 06:48:58 +08:00
|
|
|
}
|
2012-11-28 14:23:12 +08:00
|
|
|
|
|
|
|
// Handle member functions.
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) {
|
2011-05-26 04:50:04 +08:00
|
|
|
if (Method->isCopyAssignmentOperator()) {
|
2012-11-30 13:11:39 +08:00
|
|
|
SMKind |= SMF_CopyAssignment;
|
2011-04-24 07:10:33 +08:00
|
|
|
|
2018-04-03 08:11:50 +08:00
|
|
|
const auto *ParamTy =
|
|
|
|
Method->getParamDecl(0)->getType()->getAs<ReferenceType>();
|
2012-11-28 14:23:12 +08:00
|
|
|
if (!ParamTy || ParamTy->getPointeeType().isConstQualified())
|
|
|
|
data().HasDeclaredCopyAssignmentWithConstParam = true;
|
2011-05-26 04:50:04 +08:00
|
|
|
}
|
|
|
|
|
2012-11-30 13:11:39 +08:00
|
|
|
if (Method->isMoveAssignmentOperator())
|
|
|
|
SMKind |= SMF_MoveAssignment;
|
2011-04-24 07:10:33 +08:00
|
|
|
|
2010-09-29 12:25:11 +08:00
|
|
|
// Keep the list of conversion functions up-to-date.
|
2018-04-03 08:11:50 +08:00
|
|
|
if (auto *Conversion = dyn_cast<CXXConversionDecl>(D)) {
|
2013-04-09 01:12:58 +08:00
|
|
|
// FIXME: We use the 'unsafe' accessor for the access specifier here,
|
|
|
|
// because Sema may not have set it yet. That's really just a misdesign
|
|
|
|
// in Sema. However, LLDB *will* have set the access specifier correctly,
|
|
|
|
// and adds declarations after the class is technically completed,
|
|
|
|
// so completeDefinition()'s overriding of the access specifiers doesn't
|
|
|
|
// work.
|
|
|
|
AccessSpecifier AS = Conversion->getAccessUnsafe();
|
|
|
|
|
2012-11-30 13:11:39 +08:00
|
|
|
if (Conversion->getPrimaryTemplate()) {
|
|
|
|
// We don't record specializations.
|
2010-09-29 12:25:11 +08:00
|
|
|
} else {
|
2013-08-30 12:46:40 +08:00
|
|
|
ASTContext &Ctx = getASTContext();
|
|
|
|
ASTUnresolvedSet &Conversions = data().Conversions.get(Ctx);
|
|
|
|
NamedDecl *Primary =
|
|
|
|
FunTmpl ? cast<NamedDecl>(FunTmpl) : cast<NamedDecl>(Conversion);
|
|
|
|
if (Primary->getPreviousDecl())
|
|
|
|
Conversions.replace(cast<NamedDecl>(Primary->getPreviousDecl()),
|
|
|
|
Primary, AS);
|
2010-09-29 12:25:11 +08:00
|
|
|
else
|
2013-08-30 12:46:40 +08:00
|
|
|
Conversions.addDecl(Ctx, Primary, AS);
|
2010-09-29 12:25:11 +08:00
|
|
|
}
|
|
|
|
}
|
2012-11-28 14:23:12 +08:00
|
|
|
|
2012-11-30 13:11:39 +08:00
|
|
|
if (SMKind) {
|
2012-12-08 10:53:02 +08:00
|
|
|
// If this is the first declaration of a special member, we no longer have
|
|
|
|
// an implicit trivial special member.
|
|
|
|
data().HasTrivialSpecialMembers &=
|
2018-02-06 04:23:22 +08:00
|
|
|
data().DeclaredSpecialMembers | ~SMKind;
|
|
|
|
data().HasTrivialSpecialMembersForCall &=
|
|
|
|
data().DeclaredSpecialMembers | ~SMKind;
|
2012-12-08 10:53:02 +08:00
|
|
|
|
|
|
|
if (!Method->isImplicit() && !Method->isUserProvided()) {
|
|
|
|
// This method is user-declared but not user-provided. We can't work out
|
|
|
|
// whether it's trivial yet (not until we get to the end of the class).
|
|
|
|
// We'll handle this method in finishedDefaultedOrDeletedMember.
|
2018-02-06 04:23:22 +08:00
|
|
|
} else if (Method->isTrivial()) {
|
2012-12-08 10:53:02 +08:00
|
|
|
data().HasTrivialSpecialMembers |= SMKind;
|
2018-02-06 04:23:22 +08:00
|
|
|
data().HasTrivialSpecialMembersForCall |= SMKind;
|
|
|
|
} else if (Method->isTrivialForCall()) {
|
|
|
|
data().HasTrivialSpecialMembersForCall |= SMKind;
|
2012-12-08 10:53:02 +08:00
|
|
|
data().DeclaredNonTrivialSpecialMembers |= SMKind;
|
2018-02-06 04:23:22 +08:00
|
|
|
} else {
|
|
|
|
data().DeclaredNonTrivialSpecialMembers |= SMKind;
|
|
|
|
// If this is a user-provided function, do not set
|
|
|
|
// DeclaredNonTrivialSpecialMembersForCall here since we don't know
|
|
|
|
// yet whether the method would be considered non-trivial for the
|
|
|
|
// purpose of calls (attribute "trivial_abi" can be dropped from the
|
|
|
|
// class later, which can change the special method's triviality).
|
|
|
|
if (!Method->isUserProvided())
|
|
|
|
data().DeclaredNonTrivialSpecialMembersForCall |= SMKind;
|
|
|
|
}
|
2012-12-08 10:53:02 +08:00
|
|
|
|
2012-11-30 13:11:39 +08:00
|
|
|
// Note when we have declared a declared special member, and suppress the
|
|
|
|
// implicit declaration of this special member.
|
|
|
|
data().DeclaredSpecialMembers |= SMKind;
|
|
|
|
|
|
|
|
if (!Method->isImplicit()) {
|
|
|
|
data().UserDeclaredSpecialMembers |= SMKind;
|
|
|
|
|
|
|
|
// C++03 [class]p4:
|
|
|
|
// A POD-struct is an aggregate class that has [...] no user-defined
|
|
|
|
// copy assignment operator and no user-defined destructor.
|
|
|
|
//
|
|
|
|
// Since the POD bit is meant to be C++03 POD-ness, and in C++03,
|
|
|
|
// aggregates could not have any constructors, clear it even for an
|
|
|
|
// explicitly defaulted or deleted constructor.
|
|
|
|
// type is technically an aggregate in C++0x since it wouldn't be in 03.
|
|
|
|
//
|
|
|
|
// Also, a user-declared move assignment operator makes a class non-POD.
|
|
|
|
// This is an extension in C++03.
|
|
|
|
data().PlainOldData = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-06 04:52:13 +08:00
|
|
|
return;
|
2010-09-28 06:06:20 +08:00
|
|
|
}
|
2012-11-30 13:11:39 +08:00
|
|
|
|
2010-09-29 03:45:33 +08:00
|
|
|
// Handle non-static data members.
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *Field = dyn_cast<FieldDecl>(D)) {
|
2018-05-07 14:43:30 +08:00
|
|
|
ASTContext &Context = getASTContext();
|
|
|
|
|
2018-04-06 02:55:37 +08:00
|
|
|
// C++2a [class]p7:
|
|
|
|
// A standard-layout class is a class that:
|
|
|
|
// [...]
|
|
|
|
// -- has all non-static data members and bit-fields in the class and
|
|
|
|
// its base classes first declared in the same class
|
|
|
|
if (data().HasBasesWithFields)
|
|
|
|
data().IsStandardLayout = false;
|
|
|
|
|
2011-10-11 01:22:13 +08:00
|
|
|
// C++ [class.bit]p2:
|
2018-07-31 03:24:48 +08:00
|
|
|
// A declaration for a bit-field that omits the identifier declares an
|
|
|
|
// unnamed bit-field. Unnamed bit-fields are not members and cannot be
|
2011-10-11 01:22:13 +08:00
|
|
|
// initialized.
|
2018-05-07 14:43:30 +08:00
|
|
|
if (Field->isUnnamedBitfield()) {
|
|
|
|
// C++ [meta.unary.prop]p4: [LWG2358]
|
|
|
|
// T is a class type [...] with [...] no unnamed bit-fields of non-zero
|
|
|
|
// length
|
|
|
|
if (data().Empty && !Field->isZeroLengthBitField(Context) &&
|
|
|
|
Context.getLangOpts().getClangABICompat() >
|
|
|
|
LangOptions::ClangABI::Ver6)
|
|
|
|
data().Empty = false;
|
2011-10-11 01:22:13 +08:00
|
|
|
return;
|
2018-05-07 14:43:30 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2018-04-06 02:55:37 +08:00
|
|
|
// C++11 [class]p7:
|
|
|
|
// A standard-layout class is a class that:
|
|
|
|
// -- either has no non-static data members in the most derived class
|
|
|
|
// [...] or has no base classes with non-static data members
|
|
|
|
if (data().HasBasesWithNonStaticDataMembers)
|
|
|
|
data().IsCXX11StandardLayout = false;
|
|
|
|
|
2010-09-29 03:45:33 +08:00
|
|
|
// C++ [dcl.init.aggr]p1:
|
|
|
|
// An aggregate is an array or a class (clause 9) with [...] no
|
|
|
|
// private or protected non-static data members (clause 11).
|
|
|
|
//
|
2018-07-31 03:24:48 +08:00
|
|
|
// A POD must be an aggregate.
|
2010-09-29 03:45:33 +08:00
|
|
|
if (D->getAccess() == AS_private || D->getAccess() == AS_protected) {
|
|
|
|
data().Aggregate = false;
|
|
|
|
data().PlainOldData = false;
|
2020-09-21 11:10:02 +08:00
|
|
|
|
|
|
|
// C++20 [temp.param]p7:
|
|
|
|
// A structural type is [...] a literal class type [for which] all
|
|
|
|
// non-static data members are public
|
|
|
|
data().StructuralIfLiteral = false;
|
2010-09-29 03:45:33 +08:00
|
|
|
}
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
|
2018-04-06 02:55:37 +08:00
|
|
|
// Track whether this is the first field. We use this when checking
|
|
|
|
// whether the class is standard-layout below.
|
|
|
|
bool IsFirstField = !data().HasPrivateFields &&
|
|
|
|
!data().HasProtectedFields && !data().HasPublicFields;
|
|
|
|
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
// C++0x [class]p7:
|
|
|
|
// A standard-layout class is a class that:
|
|
|
|
// [...]
|
|
|
|
// -- has the same access control for all non-static data members,
|
|
|
|
switch (D->getAccess()) {
|
|
|
|
case AS_private: data().HasPrivateFields = true; break;
|
|
|
|
case AS_protected: data().HasProtectedFields = true; break;
|
|
|
|
case AS_public: data().HasPublicFields = true; break;
|
2011-09-23 13:06:16 +08:00
|
|
|
case AS_none: llvm_unreachable("Invalid access specifier");
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
};
|
|
|
|
if ((data().HasPrivateFields + data().HasProtectedFields +
|
2018-04-06 02:55:37 +08:00
|
|
|
data().HasPublicFields) > 1) {
|
2011-04-30 18:07:30 +08:00
|
|
|
data().IsStandardLayout = false;
|
2018-04-06 02:55:37 +08:00
|
|
|
data().IsCXX11StandardLayout = false;
|
|
|
|
}
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
|
2011-05-13 09:05:07 +08:00
|
|
|
// Keep track of the presence of mutable fields.
|
2020-09-21 11:10:02 +08:00
|
|
|
if (Field->isMutable()) {
|
2011-05-13 09:05:07 +08:00
|
|
|
data().HasMutableFields = true;
|
2013-12-10 16:25:00 +08:00
|
|
|
|
2020-09-21 11:10:02 +08:00
|
|
|
// C++20 [temp.param]p7:
|
|
|
|
// A structural type is [...] a literal class type [for which] all
|
|
|
|
// non-static data members are public
|
|
|
|
data().StructuralIfLiteral = false;
|
|
|
|
}
|
|
|
|
|
2013-12-10 16:25:00 +08:00
|
|
|
// C++11 [class.union]p8, DR1460:
|
|
|
|
// If X is a union, a non-static data member of X that is not an anonymous
|
|
|
|
// union is a variant member of X.
|
|
|
|
if (isUnion() && !Field->isAnonymousStructOrUnion())
|
|
|
|
data().HasVariantMembers = true;
|
|
|
|
|
2011-04-24 07:10:33 +08:00
|
|
|
// C++0x [class]p9:
|
2018-07-31 03:24:48 +08:00
|
|
|
// A POD struct is a class that is both a trivial class and a
|
|
|
|
// standard-layout class, and has no non-static data members of type
|
2010-09-29 03:45:33 +08:00
|
|
|
// non-POD struct, non-POD union (or array of such types).
|
2011-06-16 07:02:42 +08:00
|
|
|
//
|
|
|
|
// Automatic Reference Counting: the presence of a member of Objective-C pointer type
|
|
|
|
// that does not explicitly have no lifetime makes the class a non-POD.
|
2010-09-29 03:45:33 +08:00
|
|
|
QualType T = Context.getBaseElementType(Field->getType());
|
2011-06-16 07:02:42 +08:00
|
|
|
if (T->isObjCRetainableType() || T.isObjCGCStrong()) {
|
2017-03-30 01:31:42 +08:00
|
|
|
if (T.hasNonTrivialObjCLifetime()) {
|
2014-09-26 23:27:29 +08:00
|
|
|
// Objective-C Automatic Reference Counting:
|
|
|
|
// If a class has a non-static data member of Objective-C pointer
|
|
|
|
// type (or array thereof), it is a non-POD type and its
|
|
|
|
// default constructor (if any), copy constructor, move constructor,
|
|
|
|
// copy assignment operator, move assignment operator, and destructor are
|
|
|
|
// non-trivial.
|
|
|
|
setHasObjectMember(true);
|
|
|
|
struct DefinitionData &Data = data();
|
|
|
|
Data.PlainOldData = false;
|
|
|
|
Data.HasTrivialSpecialMembers = 0;
|
2018-03-29 05:13:14 +08:00
|
|
|
|
|
|
|
// __strong or __weak fields do not make special functions non-trivial
|
|
|
|
// for the purpose of calls.
|
|
|
|
Qualifiers::ObjCLifetime LT = T.getQualifiers().getObjCLifetime();
|
|
|
|
if (LT != Qualifiers::OCL_Strong && LT != Qualifiers::OCL_Weak)
|
|
|
|
data().HasTrivialSpecialMembersForCall = 0;
|
|
|
|
|
|
|
|
// Structs with __weak fields should never be passed directly.
|
|
|
|
if (LT == Qualifiers::OCL_Weak)
|
2018-04-10 06:48:22 +08:00
|
|
|
setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
|
2018-03-29 05:13:14 +08:00
|
|
|
|
2014-09-26 23:27:29 +08:00
|
|
|
Data.HasIrrelevantDestructor = false;
|
2019-02-02 10:23:40 +08:00
|
|
|
|
|
|
|
if (isUnion()) {
|
|
|
|
data().DefaultedCopyConstructorIsDeleted = true;
|
|
|
|
data().DefaultedMoveConstructorIsDeleted = true;
|
2020-06-05 10:16:05 +08:00
|
|
|
data().DefaultedCopyAssignmentIsDeleted = true;
|
2019-02-02 10:23:40 +08:00
|
|
|
data().DefaultedMoveAssignmentIsDeleted = true;
|
|
|
|
data().DefaultedDestructorIsDeleted = true;
|
|
|
|
data().NeedOverloadResolutionForCopyConstructor = true;
|
|
|
|
data().NeedOverloadResolutionForMoveConstructor = true;
|
2020-06-05 10:16:05 +08:00
|
|
|
data().NeedOverloadResolutionForCopyAssignment = true;
|
2019-02-02 10:23:40 +08:00
|
|
|
data().NeedOverloadResolutionForMoveAssignment = true;
|
|
|
|
data().NeedOverloadResolutionForDestructor = true;
|
|
|
|
}
|
2017-03-30 01:31:42 +08:00
|
|
|
} else if (!Context.getLangOpts().ObjCAutoRefCount) {
|
|
|
|
setHasObjectMember(true);
|
2014-09-26 23:27:29 +08:00
|
|
|
}
|
2013-07-20 09:06:31 +08:00
|
|
|
} else if (!T.isCXX98PODType(Context))
|
2010-09-29 03:45:33 +08:00
|
|
|
data().PlainOldData = false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
if (T->isReferenceType()) {
|
2012-12-08 10:01:17 +08:00
|
|
|
if (!Field->hasInClassInitializer())
|
|
|
|
data().HasUninitializedReferenceMember = true;
|
2011-04-24 10:49:34 +08:00
|
|
|
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
// C++0x [class]p7:
|
|
|
|
// A standard-layout class is a class that:
|
|
|
|
// -- has no non-static data members of type [...] reference,
|
2011-04-30 18:07:30 +08:00
|
|
|
data().IsStandardLayout = false;
|
2018-04-06 02:55:37 +08:00
|
|
|
data().IsCXX11StandardLayout = false;
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
|
|
|
|
// C++1z [class.copy.ctor]p10:
|
|
|
|
// A defaulted copy constructor for a class X is defined as deleted if X has:
|
|
|
|
// -- a non-static data member of rvalue reference type
|
|
|
|
if (T->isRValueReferenceType())
|
|
|
|
data().DefaultedCopyConstructorIsDeleted = true;
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
}
|
|
|
|
|
2016-02-19 09:52:46 +08:00
|
|
|
if (!Field->hasInClassInitializer() && !Field->isMutable()) {
|
2016-10-29 03:11:18 +08:00
|
|
|
if (CXXRecordDecl *FieldType = T->getAsCXXRecordDecl()) {
|
2016-02-19 10:51:07 +08:00
|
|
|
if (FieldType->hasDefinition() && !FieldType->allowConstDefaultInit())
|
2016-02-19 09:52:46 +08:00
|
|
|
data().HasUninitializedFields = true;
|
|
|
|
} else {
|
|
|
|
data().HasUninitializedFields = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-13 11:54:03 +08:00
|
|
|
// Record if this field is the first non-literal or volatile field or base.
|
2013-04-22 23:31:51 +08:00
|
|
|
if (!T->isLiteralType(Context) || T.isVolatileQualified())
|
2011-04-24 10:49:34 +08:00
|
|
|
data().HasNonLiteralTypeFieldsOrBases = true;
|
|
|
|
|
2013-12-10 16:25:00 +08:00
|
|
|
if (Field->hasInClassInitializer() ||
|
|
|
|
(Field->isAnonymousStructOrUnion() &&
|
|
|
|
Field->getType()->getAsCXXRecordDecl()->hasInClassInitializer())) {
|
2012-05-07 09:07:30 +08:00
|
|
|
data().HasInClassInitializer = true;
|
|
|
|
|
|
|
|
// C++11 [class]p5:
|
2011-06-12 01:19:42 +08:00
|
|
|
// A default constructor is trivial if [...] no non-static data member
|
|
|
|
// of its class has a brace-or-equal-initializer.
|
2012-11-30 13:11:39 +08:00
|
|
|
data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor;
|
2011-06-12 01:19:42 +08:00
|
|
|
|
2012-05-07 09:07:30 +08:00
|
|
|
// C++11 [dcl.init.aggr]p1:
|
2011-06-12 01:19:42 +08:00
|
|
|
// An aggregate is a [...] class with [...] no
|
|
|
|
// brace-or-equal-initializers for non-static data members.
|
2013-04-21 06:23:05 +08:00
|
|
|
//
|
2016-03-09 06:17:41 +08:00
|
|
|
// This rule was removed in C++14.
|
2014-08-19 23:55:55 +08:00
|
|
|
if (!getASTContext().getLangOpts().CPlusPlus14)
|
2013-04-21 06:23:05 +08:00
|
|
|
data().Aggregate = false;
|
2011-06-12 01:19:42 +08:00
|
|
|
|
2012-05-07 09:07:30 +08:00
|
|
|
// C++11 [class]p10:
|
2011-06-12 01:19:42 +08:00
|
|
|
// A POD struct is [...] a trivial class.
|
|
|
|
data().PlainOldData = false;
|
|
|
|
}
|
|
|
|
|
2012-12-08 16:32:28 +08:00
|
|
|
// C++11 [class.copy]p23:
|
|
|
|
// A defaulted copy/move assignment operator for a class X is defined
|
|
|
|
// as deleted if X has:
|
|
|
|
// -- a non-static data member of reference type
|
2020-06-05 10:16:05 +08:00
|
|
|
if (T->isReferenceType()) {
|
|
|
|
data().DefaultedCopyAssignmentIsDeleted = true;
|
2012-12-08 16:32:28 +08:00
|
|
|
data().DefaultedMoveAssignmentIsDeleted = true;
|
2020-06-05 10:16:05 +08:00
|
|
|
}
|
2012-12-08 16:32:28 +08:00
|
|
|
|
2019-06-21 04:44:45 +08:00
|
|
|
// Bitfields of length 0 are also zero-sized, but we already bailed out for
|
|
|
|
// those because they are always unnamed.
|
|
|
|
bool IsZeroSize = Field->isZeroSize(Context);
|
|
|
|
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *RecordTy = T->getAs<RecordType>()) {
|
|
|
|
auto *FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
|
2010-09-29 04:50:54 +08:00
|
|
|
if (FieldRec->getDefinition()) {
|
2012-12-08 16:32:28 +08:00
|
|
|
addedClassSubobject(FieldRec);
|
|
|
|
|
2013-11-25 15:07:05 +08:00
|
|
|
// We may need to perform overload resolution to determine whether a
|
|
|
|
// field can be moved if it's const or volatile qualified.
|
|
|
|
if (T.getCVRQualifiers() & (Qualifiers::Const | Qualifiers::Volatile)) {
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
// We need to care about 'const' for the copy constructor because an
|
|
|
|
// implicit copy constructor might be declared with a non-const
|
|
|
|
// parameter.
|
|
|
|
data().NeedOverloadResolutionForCopyConstructor = true;
|
2013-11-25 15:07:05 +08:00
|
|
|
data().NeedOverloadResolutionForMoveConstructor = true;
|
2020-06-05 10:16:05 +08:00
|
|
|
data().NeedOverloadResolutionForCopyAssignment = true;
|
2013-11-25 15:07:05 +08:00
|
|
|
data().NeedOverloadResolutionForMoveAssignment = true;
|
|
|
|
}
|
|
|
|
|
2012-12-08 16:32:28 +08:00
|
|
|
// C++11 [class.ctor]p5, C++11 [class.copy]p11:
|
|
|
|
// A defaulted [special member] for a class X is defined as
|
|
|
|
// deleted if:
|
|
|
|
// -- X is a union-like class that has a variant member with a
|
|
|
|
// non-trivial [corresponding special member]
|
|
|
|
if (isUnion()) {
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
if (FieldRec->hasNonTrivialCopyConstructor())
|
|
|
|
data().DefaultedCopyConstructorIsDeleted = true;
|
2012-12-08 16:32:28 +08:00
|
|
|
if (FieldRec->hasNonTrivialMoveConstructor())
|
|
|
|
data().DefaultedMoveConstructorIsDeleted = true;
|
2020-06-05 10:16:05 +08:00
|
|
|
if (FieldRec->hasNonTrivialCopyAssignment())
|
|
|
|
data().DefaultedCopyAssignmentIsDeleted = true;
|
2012-12-08 16:32:28 +08:00
|
|
|
if (FieldRec->hasNonTrivialMoveAssignment())
|
|
|
|
data().DefaultedMoveAssignmentIsDeleted = true;
|
|
|
|
if (FieldRec->hasNonTrivialDestructor())
|
|
|
|
data().DefaultedDestructorIsDeleted = true;
|
|
|
|
}
|
|
|
|
|
2016-08-16 08:13:47 +08:00
|
|
|
// For an anonymous union member, our overload resolution will perform
|
|
|
|
// overload resolution for its members.
|
|
|
|
if (Field->isAnonymousStructOrUnion()) {
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
data().NeedOverloadResolutionForCopyConstructor |=
|
|
|
|
FieldRec->data().NeedOverloadResolutionForCopyConstructor;
|
2016-08-16 08:13:47 +08:00
|
|
|
data().NeedOverloadResolutionForMoveConstructor |=
|
|
|
|
FieldRec->data().NeedOverloadResolutionForMoveConstructor;
|
2020-06-05 10:16:05 +08:00
|
|
|
data().NeedOverloadResolutionForCopyAssignment |=
|
|
|
|
FieldRec->data().NeedOverloadResolutionForCopyAssignment;
|
2016-08-16 08:13:47 +08:00
|
|
|
data().NeedOverloadResolutionForMoveAssignment |=
|
|
|
|
FieldRec->data().NeedOverloadResolutionForMoveAssignment;
|
|
|
|
data().NeedOverloadResolutionForDestructor |=
|
|
|
|
FieldRec->data().NeedOverloadResolutionForDestructor;
|
|
|
|
}
|
|
|
|
|
2011-05-10 02:22:59 +08:00
|
|
|
// C++0x [class.ctor]p5:
|
2011-12-22 10:22:31 +08:00
|
|
|
// A default constructor is trivial [...] if:
|
2011-05-10 02:22:59 +08:00
|
|
|
// -- for all the non-static data members of its class that are of
|
|
|
|
// class type (or array thereof), each such class has a trivial
|
|
|
|
// default constructor.
|
|
|
|
if (!FieldRec->hasTrivialDefaultConstructor())
|
2012-11-30 13:11:39 +08:00
|
|
|
data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor;
|
2011-04-24 07:10:33 +08:00
|
|
|
|
|
|
|
// C++0x [class.copy]p13:
|
|
|
|
// A copy/move constructor for class X is trivial if [...]
|
|
|
|
// [...]
|
|
|
|
// -- for each non-static data member of X that is of class type (or
|
|
|
|
// an array thereof), the constructor selected to copy/move that
|
|
|
|
// member is trivial;
|
2010-09-29 04:50:54 +08:00
|
|
|
if (!FieldRec->hasTrivialCopyConstructor())
|
2012-11-30 13:11:39 +08:00
|
|
|
data().HasTrivialSpecialMembers &= ~SMF_CopyConstructor;
|
2018-02-06 04:23:22 +08:00
|
|
|
|
|
|
|
if (!FieldRec->hasTrivialCopyConstructorForCall())
|
|
|
|
data().HasTrivialSpecialMembersForCall &= ~SMF_CopyConstructor;
|
|
|
|
|
2012-12-08 16:32:28 +08:00
|
|
|
// If the field doesn't have a simple move constructor, we'll eagerly
|
|
|
|
// declare the move constructor for this class and we'll decide whether
|
|
|
|
// it's trivial then.
|
2012-11-16 08:53:38 +08:00
|
|
|
if (!FieldRec->hasTrivialMoveConstructor())
|
2012-11-30 13:11:39 +08:00
|
|
|
data().HasTrivialSpecialMembers &= ~SMF_MoveConstructor;
|
2011-04-24 07:10:33 +08:00
|
|
|
|
2018-02-06 04:23:22 +08:00
|
|
|
if (!FieldRec->hasTrivialMoveConstructorForCall())
|
|
|
|
data().HasTrivialSpecialMembersForCall &= ~SMF_MoveConstructor;
|
|
|
|
|
2011-04-24 07:10:33 +08:00
|
|
|
// C++0x [class.copy]p27:
|
|
|
|
// A copy/move assignment operator for class X is trivial if [...]
|
|
|
|
// [...]
|
|
|
|
// -- for each non-static data member of X that is of class type (or
|
|
|
|
// an array thereof), the assignment operator selected to
|
|
|
|
// copy/move that member is trivial;
|
2010-09-29 04:50:54 +08:00
|
|
|
if (!FieldRec->hasTrivialCopyAssignment())
|
2012-11-30 13:11:39 +08:00
|
|
|
data().HasTrivialSpecialMembers &= ~SMF_CopyAssignment;
|
2012-12-08 16:32:28 +08:00
|
|
|
// If the field doesn't have a simple move assignment, we'll eagerly
|
|
|
|
// declare the move assignment for this class and we'll decide whether
|
|
|
|
// it's trivial then.
|
2012-11-16 08:53:38 +08:00
|
|
|
if (!FieldRec->hasTrivialMoveAssignment())
|
2012-11-30 13:11:39 +08:00
|
|
|
data().HasTrivialSpecialMembers &= ~SMF_MoveAssignment;
|
2011-04-24 07:10:33 +08:00
|
|
|
|
2010-09-29 04:50:54 +08:00
|
|
|
if (!FieldRec->hasTrivialDestructor())
|
2012-11-30 13:11:39 +08:00
|
|
|
data().HasTrivialSpecialMembers &= ~SMF_Destructor;
|
2018-02-06 04:23:22 +08:00
|
|
|
if (!FieldRec->hasTrivialDestructorForCall())
|
|
|
|
data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;
|
2012-02-25 15:33:38 +08:00
|
|
|
if (!FieldRec->hasIrrelevantDestructor())
|
|
|
|
data().HasIrrelevantDestructor = false;
|
2011-06-16 07:02:42 +08:00
|
|
|
if (FieldRec->hasObjectMember())
|
|
|
|
setHasObjectMember(true);
|
2013-01-26 07:57:05 +08:00
|
|
|
if (FieldRec->hasVolatileMember())
|
|
|
|
setHasVolatileMember(true);
|
2018-04-10 06:48:22 +08:00
|
|
|
if (FieldRec->getArgPassingRestrictions() ==
|
|
|
|
RecordDecl::APK_CanNeverPassInRegs)
|
|
|
|
setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
|
|
|
|
// C++0x [class]p7:
|
|
|
|
// A standard-layout class is a class that:
|
|
|
|
// -- has no non-static data members of type non-standard-layout
|
|
|
|
// class (or array of such types) [...]
|
2011-04-30 18:07:30 +08:00
|
|
|
if (!FieldRec->isStandardLayout())
|
|
|
|
data().IsStandardLayout = false;
|
2018-04-06 02:55:37 +08:00
|
|
|
if (!FieldRec->isCXX11StandardLayout())
|
|
|
|
data().IsCXX11StandardLayout = false;
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
|
2018-04-06 02:55:37 +08:00
|
|
|
// C++2a [class]p7:
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
// A standard-layout class is a class that:
|
|
|
|
// [...]
|
2018-04-06 02:55:37 +08:00
|
|
|
// -- has no element of the set M(S) of types as a base class.
|
2019-06-21 04:44:45 +08:00
|
|
|
if (data().IsStandardLayout &&
|
|
|
|
(isUnion() || IsFirstField || IsZeroSize) &&
|
2018-04-06 02:55:37 +08:00
|
|
|
hasSubobjectAtOffsetZeroOfEmptyBaseType(Context, FieldRec))
|
|
|
|
data().IsStandardLayout = false;
|
|
|
|
|
|
|
|
// C++11 [class]p7:
|
|
|
|
// A standard-layout class is a class that:
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
// -- has no base classes of the same type as the first non-static
|
2018-04-06 02:55:37 +08:00
|
|
|
// data member
|
|
|
|
if (data().IsCXX11StandardLayout && IsFirstField) {
|
|
|
|
// FIXME: We should check all base classes here, not just direct
|
|
|
|
// base classes.
|
2014-03-13 23:41:46 +08:00
|
|
|
for (const auto &BI : bases()) {
|
|
|
|
if (Context.hasSameUnqualifiedType(BI.getType(), T)) {
|
2018-04-06 02:55:37 +08:00
|
|
|
data().IsCXX11StandardLayout = false;
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-04-06 02:55:37 +08:00
|
|
|
|
2011-05-13 09:05:07 +08:00
|
|
|
// Keep track of the presence of mutable fields.
|
2020-06-05 10:16:05 +08:00
|
|
|
if (FieldRec->hasMutableFields())
|
2011-05-13 09:05:07 +08:00
|
|
|
data().HasMutableFields = true;
|
2020-06-05 10:16:05 +08:00
|
|
|
|
|
|
|
if (Field->isMutable()) {
|
|
|
|
// Our copy constructor/assignment might call something other than
|
|
|
|
// the subobject's copy constructor/assignment if it's mutable and of
|
|
|
|
// class type.
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
data().NeedOverloadResolutionForCopyConstructor = true;
|
2020-06-05 10:16:05 +08:00
|
|
|
data().NeedOverloadResolutionForCopyAssignment = true;
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
}
|
2011-12-22 10:22:31 +08:00
|
|
|
|
|
|
|
// C++11 [class.copy]p13:
|
|
|
|
// If the implicitly-defined constructor would satisfy the
|
|
|
|
// requirements of a constexpr constructor, the implicitly-defined
|
|
|
|
// constructor is constexpr.
|
|
|
|
// C++11 [dcl.constexpr]p4:
|
|
|
|
// -- every constructor involved in initializing non-static data
|
|
|
|
// members [...] shall be a constexpr constructor
|
|
|
|
if (!Field->hasInClassInitializer() &&
|
2012-05-07 09:07:30 +08:00
|
|
|
!FieldRec->hasConstexprDefaultConstructor() && !isUnion())
|
2011-12-22 10:22:31 +08:00
|
|
|
// The standard requires any in-class initializer to be a constant
|
|
|
|
// expression. We consider this to be a defect.
|
|
|
|
data().DefaultedDefaultConstructorIsConstexpr = false;
|
2012-11-28 14:23:12 +08:00
|
|
|
|
|
|
|
// C++11 [class.copy]p8:
|
|
|
|
// The implicitly-declared copy constructor for a class X will have
|
C++ DR1611, 1658, 2180: implement "potentially constructed subobject" rules for special member functions.
Essentially, as a base class constructor does not construct virtual bases, such
a constructor for an abstract class does not need the corresponding base class
construction to be valid, and likewise for destructors.
This creates an awkward situation: clang will sometimes generate references to
the complete object and deleting destructors for an abstract class (it puts
them in the construction vtable for a derived class). But we can't generate a
"correct" version of these because we can't generate references to base class
constructors any more (if they're template specializations, say, we might not
have instantiated them and can't assume any other TU will emit a copy).
Fortunately, we don't need to, since no correct program can ever invoke them,
so instead emit symbols that just trap.
We should stop emitting references to these symbols, but still need to emit
definitions for compatibility.
llvm-svn: 296275
2017-02-26 07:53:05 +08:00
|
|
|
// the form 'X::X(const X&)' if each potentially constructed subobject
|
|
|
|
// of a class type M (or array thereof) has a copy constructor whose
|
|
|
|
// first parameter is of type 'const M&' or 'const volatile M&'.
|
2012-11-28 14:23:12 +08:00
|
|
|
if (!FieldRec->hasCopyConstructorWithConstParam())
|
C++ DR1611, 1658, 2180: implement "potentially constructed subobject" rules for special member functions.
Essentially, as a base class constructor does not construct virtual bases, such
a constructor for an abstract class does not need the corresponding base class
construction to be valid, and likewise for destructors.
This creates an awkward situation: clang will sometimes generate references to
the complete object and deleting destructors for an abstract class (it puts
them in the construction vtable for a derived class). But we can't generate a
"correct" version of these because we can't generate references to base class
constructors any more (if they're template specializations, say, we might not
have instantiated them and can't assume any other TU will emit a copy).
Fortunately, we don't need to, since no correct program can ever invoke them,
so instead emit symbols that just trap.
We should stop emitting references to these symbols, but still need to emit
definitions for compatibility.
llvm-svn: 296275
2017-02-26 07:53:05 +08:00
|
|
|
data().ImplicitCopyConstructorCanHaveConstParamForNonVBase = false;
|
2012-11-28 14:23:12 +08:00
|
|
|
|
|
|
|
// C++11 [class.copy]p18:
|
|
|
|
// The implicitly-declared copy assignment oeprator for a class X will
|
|
|
|
// have the form 'X& X::operator=(const X&)' if [...] for all the
|
|
|
|
// non-static data members of X that are of a class type M (or array
|
|
|
|
// thereof), each such class type has a copy assignment operator whose
|
|
|
|
// parameter is of type 'const M&', 'const volatile M&' or 'M'.
|
|
|
|
if (!FieldRec->hasCopyAssignmentWithConstParam())
|
|
|
|
data().ImplicitCopyAssignmentHasConstParam = false;
|
2012-12-08 10:01:17 +08:00
|
|
|
|
|
|
|
if (FieldRec->hasUninitializedReferenceMember() &&
|
|
|
|
!Field->hasInClassInitializer())
|
|
|
|
data().HasUninitializedReferenceMember = true;
|
2013-12-10 16:25:00 +08:00
|
|
|
|
|
|
|
// C++11 [class.union]p8, DR1460:
|
|
|
|
// a non-static data member of an anonymous union that is a member of
|
|
|
|
// X is also a variant member of X.
|
|
|
|
if (FieldRec->hasVariantMembers() &&
|
|
|
|
Field->isAnonymousStructOrUnion())
|
|
|
|
data().HasVariantMembers = true;
|
2010-09-29 04:50:54 +08:00
|
|
|
}
|
2011-12-22 10:22:31 +08:00
|
|
|
} else {
|
|
|
|
// Base element type of field is a non-class type.
|
2013-04-22 23:31:51 +08:00
|
|
|
if (!T->isLiteralType(Context) ||
|
2019-09-19 01:37:44 +08:00
|
|
|
(!Field->hasInClassInitializer() && !isUnion() &&
|
2020-04-22 03:37:19 +08:00
|
|
|
!Context.getLangOpts().CPlusPlus20))
|
2011-12-22 10:22:31 +08:00
|
|
|
data().DefaultedDefaultConstructorIsConstexpr = false;
|
2012-12-08 16:32:28 +08:00
|
|
|
|
|
|
|
// C++11 [class.copy]p23:
|
|
|
|
// A defaulted copy/move assignment operator for a class X is defined
|
|
|
|
// as deleted if X has:
|
|
|
|
// -- a non-static data member of const non-class type (or array
|
|
|
|
// thereof)
|
2020-06-05 10:16:05 +08:00
|
|
|
if (T.isConstQualified()) {
|
|
|
|
data().DefaultedCopyAssignmentIsDeleted = true;
|
2012-12-08 16:32:28 +08:00
|
|
|
data().DefaultedMoveAssignmentIsDeleted = true;
|
2020-06-05 10:16:05 +08:00
|
|
|
}
|
2020-09-21 11:10:02 +08:00
|
|
|
|
|
|
|
// C++20 [temp.param]p7:
|
|
|
|
// A structural type is [...] a literal class type [for which] the
|
|
|
|
// types of all non-static data members are structural types or
|
|
|
|
// (possibly multidimensional) array thereof
|
|
|
|
// We deal with class types elsewhere.
|
2020-09-21 14:08:33 +08:00
|
|
|
if (!T->isStructuralType())
|
2020-09-21 11:10:02 +08:00
|
|
|
data().StructuralIfLiteral = false;
|
2010-09-29 04:50:54 +08:00
|
|
|
}
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
|
2016-05-22 13:34:26 +08:00
|
|
|
// C++14 [meta.unary.prop]p4:
|
2019-06-21 04:44:45 +08:00
|
|
|
// T is a class type [...] with [...] no non-static data members other
|
|
|
|
// than subobjects of zero size
|
|
|
|
if (data().Empty && !IsZeroSize)
|
|
|
|
data().Empty = false;
|
2010-09-29 03:45:33 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-09-29 12:25:11 +08:00
|
|
|
// Handle using declarations of conversion functions.
|
2018-04-03 08:11:50 +08:00
|
|
|
if (auto *Shadow = dyn_cast<UsingShadowDecl>(D)) {
|
2010-09-29 12:25:11 +08:00
|
|
|
if (Shadow->getDeclName().getNameKind()
|
2013-08-30 12:46:40 +08:00
|
|
|
== DeclarationName::CXXConversionFunctionName) {
|
|
|
|
ASTContext &Ctx = getASTContext();
|
|
|
|
data().Conversions.get(Ctx).addDecl(Ctx, Shadow, Shadow->getAccess());
|
|
|
|
}
|
|
|
|
}
|
2016-05-13 14:47:56 +08:00
|
|
|
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *Using = dyn_cast<UsingDecl>(D)) {
|
2016-05-13 14:47:56 +08:00
|
|
|
if (Using->getDeclName().getNameKind() ==
|
2016-12-03 09:26:47 +08:00
|
|
|
DeclarationName::CXXConstructorName) {
|
2016-05-13 14:47:56 +08:00
|
|
|
data().HasInheritedConstructor = true;
|
2016-12-03 09:26:47 +08:00
|
|
|
// C++1z [dcl.init.aggr]p1:
|
|
|
|
// An aggregate is [...] a class [...] with no inherited constructors
|
|
|
|
data().Aggregate = false;
|
|
|
|
}
|
2016-05-13 14:47:56 +08:00
|
|
|
|
|
|
|
if (Using->getDeclName().getCXXOverloadedOperator() == OO_Equal)
|
|
|
|
data().HasInheritedAssignment = true;
|
|
|
|
}
|
2012-09-01 06:18:20 +08:00
|
|
|
}
|
|
|
|
|
2012-12-08 10:53:02 +08:00
|
|
|
void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) {
|
|
|
|
assert(!D->isImplicit() && !D->isUserProvided());
|
|
|
|
|
|
|
|
// The kind of special member this declaration is, if any.
|
|
|
|
unsigned SMKind = 0;
|
|
|
|
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
|
2012-12-08 10:53:02 +08:00
|
|
|
if (Constructor->isDefaultConstructor()) {
|
|
|
|
SMKind |= SMF_DefaultConstructor;
|
|
|
|
if (Constructor->isConstexpr())
|
|
|
|
data().HasConstexprDefaultConstructor = true;
|
|
|
|
}
|
|
|
|
if (Constructor->isCopyConstructor())
|
|
|
|
SMKind |= SMF_CopyConstructor;
|
|
|
|
else if (Constructor->isMoveConstructor())
|
|
|
|
SMKind |= SMF_MoveConstructor;
|
|
|
|
else if (Constructor->isConstexpr())
|
|
|
|
// We may now know that the constructor is constexpr.
|
|
|
|
data().HasConstexprNonCopyMoveConstructor = true;
|
2014-03-28 04:23:12 +08:00
|
|
|
} else if (isa<CXXDestructorDecl>(D)) {
|
2012-12-08 10:53:02 +08:00
|
|
|
SMKind |= SMF_Destructor;
|
2014-03-28 04:23:12 +08:00
|
|
|
if (!D->isTrivial() || D->getAccess() != AS_public || D->isDeleted())
|
|
|
|
data().HasIrrelevantDestructor = false;
|
|
|
|
} else if (D->isCopyAssignmentOperator())
|
2012-12-08 10:53:02 +08:00
|
|
|
SMKind |= SMF_CopyAssignment;
|
|
|
|
else if (D->isMoveAssignmentOperator())
|
|
|
|
SMKind |= SMF_MoveAssignment;
|
|
|
|
|
|
|
|
// Update which trivial / non-trivial special members we have.
|
|
|
|
// addedMember will have skipped this step for this member.
|
|
|
|
if (D->isTrivial())
|
|
|
|
data().HasTrivialSpecialMembers |= SMKind;
|
|
|
|
else
|
|
|
|
data().DeclaredNonTrivialSpecialMembers |= SMKind;
|
|
|
|
}
|
|
|
|
|
2020-07-28 22:49:05 +08:00
|
|
|
void CXXRecordDecl::setCaptures(ASTContext &Context,
|
|
|
|
ArrayRef<LambdaCapture> Captures) {
|
2020-06-05 10:15:22 +08:00
|
|
|
CXXRecordDecl::LambdaDefinitionData &Data = getLambdaData();
|
|
|
|
|
|
|
|
// Copy captures.
|
|
|
|
Data.NumCaptures = Captures.size();
|
|
|
|
Data.NumExplicitCaptures = 0;
|
|
|
|
Data.Captures = (LambdaCapture *)Context.Allocate(sizeof(LambdaCapture) *
|
|
|
|
Captures.size());
|
|
|
|
LambdaCapture *ToCapture = Data.Captures;
|
|
|
|
for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
|
|
|
|
if (Captures[I].isExplicit())
|
|
|
|
++Data.NumExplicitCaptures;
|
|
|
|
|
|
|
|
*ToCapture++ = Captures[I];
|
|
|
|
}
|
2020-06-05 10:16:05 +08:00
|
|
|
|
|
|
|
if (!lambdaIsDefaultConstructibleAndAssignable())
|
|
|
|
Data.DefaultedCopyAssignmentIsDeleted = true;
|
2020-06-05 10:15:22 +08:00
|
|
|
}
|
|
|
|
|
2018-02-06 04:23:22 +08:00
|
|
|
void CXXRecordDecl::setTrivialForCallFlags(CXXMethodDecl *D) {
|
|
|
|
unsigned SMKind = 0;
|
|
|
|
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
|
2018-02-06 04:23:22 +08:00
|
|
|
if (Constructor->isCopyConstructor())
|
|
|
|
SMKind = SMF_CopyConstructor;
|
|
|
|
else if (Constructor->isMoveConstructor())
|
|
|
|
SMKind = SMF_MoveConstructor;
|
|
|
|
} else if (isa<CXXDestructorDecl>(D))
|
|
|
|
SMKind = SMF_Destructor;
|
|
|
|
|
|
|
|
if (D->isTrivialForCall())
|
|
|
|
data().HasTrivialSpecialMembersForCall |= SMKind;
|
|
|
|
else
|
|
|
|
data().DeclaredNonTrivialSpecialMembersForCall |= SMKind;
|
|
|
|
}
|
|
|
|
|
2012-09-01 06:18:20 +08:00
|
|
|
bool CXXRecordDecl::isCLike() const {
|
|
|
|
if (getTagKind() == TTK_Class || getTagKind() == TTK_Interface ||
|
|
|
|
!TemplateOrInstantiation.isNull())
|
|
|
|
return false;
|
|
|
|
if (!hasDefinition())
|
|
|
|
return true;
|
2012-01-24 00:58:45 +08:00
|
|
|
|
2012-02-01 14:36:44 +08:00
|
|
|
return isPOD() && data().HasOnlyCMembers;
|
2012-01-24 00:58:45 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
|
|
|
bool CXXRecordDecl::isGenericLambda() const {
|
2013-10-24 00:10:50 +08:00
|
|
|
if (!isLambda()) return false;
|
|
|
|
return getLambdaData().IsGenericLambda;
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
}
|
|
|
|
|
2018-08-03 04:30:52 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
static bool allLookupResultsAreTheSame(const DeclContext::lookup_result &R) {
|
|
|
|
for (auto *D : R)
|
|
|
|
if (!declaresSameEntity(D, R.front()))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-10-01 05:24:04 +08:00
|
|
|
static NamedDecl* getLambdaCallOperatorHelper(const CXXRecordDecl &RD) {
|
2019-10-01 03:12:29 +08:00
|
|
|
if (!RD.isLambda()) return nullptr;
|
2018-07-31 03:24:48 +08:00
|
|
|
DeclarationName Name =
|
2019-10-01 03:12:29 +08:00
|
|
|
RD.getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
|
|
|
|
DeclContext::lookup_result Calls = RD.lookup(Name);
|
2013-09-30 01:08:32 +08:00
|
|
|
|
|
|
|
assert(!Calls.empty() && "Missing lambda call operator!");
|
2018-08-03 04:30:52 +08:00
|
|
|
assert(allLookupResultsAreTheSame(Calls) &&
|
|
|
|
"More than one lambda call operator!");
|
2019-10-01 03:12:29 +08:00
|
|
|
return Calls.front();
|
|
|
|
}
|
|
|
|
|
|
|
|
FunctionTemplateDecl* CXXRecordDecl::getDependentLambdaCallOperator() const {
|
|
|
|
NamedDecl *CallOp = getLambdaCallOperatorHelper(*this);
|
2019-10-01 04:45:12 +08:00
|
|
|
return dyn_cast_or_null<FunctionTemplateDecl>(CallOp);
|
2019-10-01 03:12:29 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2019-10-01 03:12:29 +08:00
|
|
|
CXXMethodDecl *CXXRecordDecl::getLambdaCallOperator() const {
|
|
|
|
NamedDecl *CallOp = getLambdaCallOperatorHelper(*this);
|
2019-10-01 04:45:12 +08:00
|
|
|
|
|
|
|
if (CallOp == nullptr)
|
|
|
|
return nullptr;
|
|
|
|
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *CallOpTmpl = dyn_cast<FunctionTemplateDecl>(CallOp))
|
2013-09-30 01:08:32 +08:00
|
|
|
return cast<CXXMethodDecl>(CallOpTmpl->getTemplatedDecl());
|
2018-07-31 03:24:48 +08:00
|
|
|
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
return cast<CXXMethodDecl>(CallOp);
|
|
|
|
}
|
|
|
|
|
|
|
|
CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
|
2014-05-12 13:36:57 +08:00
|
|
|
if (!isLambda()) return nullptr;
|
2018-07-31 03:24:48 +08:00
|
|
|
DeclarationName Name =
|
2013-09-30 01:08:32 +08:00
|
|
|
&getASTContext().Idents.get(getLambdaStaticInvokerName());
|
2015-02-21 10:45:19 +08:00
|
|
|
DeclContext::lookup_result Invoker = lookup(Name);
|
2014-05-12 13:36:57 +08:00
|
|
|
if (Invoker.empty()) return nullptr;
|
2018-08-03 04:30:52 +08:00
|
|
|
assert(allLookupResultsAreTheSame(Invoker) &&
|
|
|
|
"More than one static invoker operator!");
|
2013-09-30 01:08:32 +08:00
|
|
|
NamedDecl *InvokerFun = Invoker.front();
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *InvokerTemplate = dyn_cast<FunctionTemplateDecl>(InvokerFun))
|
2013-09-30 01:08:32 +08:00
|
|
|
return cast<CXXMethodDecl>(InvokerTemplate->getTemplatedDecl());
|
2018-07-31 03:24:48 +08:00
|
|
|
|
|
|
|
return cast<CXXMethodDecl>(InvokerFun);
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
}
|
|
|
|
|
2012-02-10 15:45:31 +08:00
|
|
|
void CXXRecordDecl::getCaptureFields(
|
|
|
|
llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
|
2012-02-11 08:18:00 +08:00
|
|
|
FieldDecl *&ThisCapture) const {
|
2012-02-10 15:45:31 +08:00
|
|
|
Captures.clear();
|
2014-05-12 13:36:57 +08:00
|
|
|
ThisCapture = nullptr;
|
2012-02-10 15:45:31 +08:00
|
|
|
|
2012-02-13 23:44:47 +08:00
|
|
|
LambdaDefinitionData &Lambda = getLambdaData();
|
2012-02-10 15:45:31 +08:00
|
|
|
RecordDecl::field_iterator Field = field_begin();
|
2014-05-11 00:31:55 +08:00
|
|
|
for (const LambdaCapture *C = Lambda.Captures, *CEnd = C + Lambda.NumCaptures;
|
2012-02-10 15:45:31 +08:00
|
|
|
C != CEnd; ++C, ++Field) {
|
2013-05-16 14:20:58 +08:00
|
|
|
if (C->capturesThis())
|
2012-06-07 04:45:41 +08:00
|
|
|
ThisCapture = *Field;
|
2013-05-16 14:20:58 +08:00
|
|
|
else if (C->capturesVariable())
|
|
|
|
Captures[C->getCapturedVar()] = *Field;
|
2012-02-10 15:45:31 +08:00
|
|
|
}
|
2013-09-28 12:02:39 +08:00
|
|
|
assert(Field == field_end());
|
2012-02-10 15:45:31 +08:00
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
TemplateParameterList *
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
CXXRecordDecl::getGenericLambdaTemplateParameterList() const {
|
2019-05-04 18:49:46 +08:00
|
|
|
if (!isGenericLambda()) return nullptr;
|
2018-07-31 03:24:48 +08:00
|
|
|
CXXMethodDecl *CallOp = getLambdaCallOperator();
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
if (FunctionTemplateDecl *Tmpl = CallOp->getDescribedFunctionTemplate())
|
|
|
|
return Tmpl->getTemplateParameters();
|
2014-05-12 13:36:57 +08:00
|
|
|
return nullptr;
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
}
|
2012-02-10 15:45:31 +08:00
|
|
|
|
2019-05-04 18:49:46 +08:00
|
|
|
ArrayRef<NamedDecl *>
|
|
|
|
CXXRecordDecl::getLambdaExplicitTemplateParameters() const {
|
|
|
|
TemplateParameterList *List = getGenericLambdaTemplateParameterList();
|
|
|
|
if (!List)
|
|
|
|
return {};
|
|
|
|
|
|
|
|
assert(std::is_partitioned(List->begin(), List->end(),
|
|
|
|
[](const NamedDecl *D) { return !D->isImplicit(); })
|
|
|
|
&& "Explicit template params should be ordered before implicit ones");
|
|
|
|
|
2019-07-03 16:13:17 +08:00
|
|
|
const auto ExplicitEnd = llvm::partition_point(
|
|
|
|
*List, [](const NamedDecl *D) { return !D->isImplicit(); });
|
2019-05-04 18:49:46 +08:00
|
|
|
return llvm::makeArrayRef(List->begin(), ExplicitEnd);
|
|
|
|
}
|
|
|
|
|
2016-08-25 08:34:00 +08:00
|
|
|
Decl *CXXRecordDecl::getLambdaContextDecl() const {
|
|
|
|
assert(isLambda() && "Not a lambda closure type!");
|
|
|
|
ExternalASTSource *Source = getParentASTContext().getExternalSource();
|
|
|
|
return getLambdaData().ContextDecl.get(Source);
|
|
|
|
}
|
|
|
|
|
2010-03-15 17:07:48 +08:00
|
|
|
static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
|
2014-01-22 15:29:52 +08:00
|
|
|
QualType T =
|
|
|
|
cast<CXXConversionDecl>(Conv->getUnderlyingDecl()->getAsFunction())
|
|
|
|
->getConversionType();
|
2010-03-15 17:07:48 +08:00
|
|
|
return Context.getCanonicalType(T);
|
2009-10-08 04:43:36 +08:00
|
|
|
}
|
|
|
|
|
2010-03-15 17:07:48 +08:00
|
|
|
/// Collect the visible conversions of a base class.
|
|
|
|
///
|
2012-06-16 06:28:09 +08:00
|
|
|
/// \param Record a base class of the class we're considering
|
2010-03-15 17:07:48 +08:00
|
|
|
/// \param InVirtual whether this base class is a virtual base (or a base
|
|
|
|
/// of a virtual base)
|
|
|
|
/// \param Access the access along the inheritance path to this base
|
|
|
|
/// \param ParentHiddenTypes the conversions provided by the inheritors
|
|
|
|
/// of this base
|
|
|
|
/// \param Output the set to which to add conversions from non-virtual bases
|
|
|
|
/// \param VOutput the set to which to add conversions from virtual bases
|
|
|
|
/// \param HiddenVBaseCs the set of conversions which were hidden in a
|
|
|
|
/// virtual base along some inheritance path
|
2019-12-24 18:09:24 +08:00
|
|
|
static void CollectVisibleConversions(
|
|
|
|
ASTContext &Context, const CXXRecordDecl *Record, bool InVirtual,
|
|
|
|
AccessSpecifier Access,
|
|
|
|
const llvm::SmallPtrSet<CanQualType, 8> &ParentHiddenTypes,
|
|
|
|
ASTUnresolvedSet &Output, UnresolvedSetImpl &VOutput,
|
|
|
|
llvm::SmallPtrSet<NamedDecl *, 8> &HiddenVBaseCs) {
|
2010-03-15 17:07:48 +08:00
|
|
|
// The set of types which have conversions in this class or its
|
|
|
|
// subclasses. As an optimization, we don't copy the derived set
|
|
|
|
// unless it might change.
|
|
|
|
const llvm::SmallPtrSet<CanQualType, 8> *HiddenTypes = &ParentHiddenTypes;
|
|
|
|
llvm::SmallPtrSet<CanQualType, 8> HiddenTypesBuffer;
|
|
|
|
|
|
|
|
// Collect the direct conversions and figure out which conversions
|
|
|
|
// will be hidden in the subclasses.
|
2012-11-28 11:56:09 +08:00
|
|
|
CXXRecordDecl::conversion_iterator ConvI = Record->conversion_begin();
|
|
|
|
CXXRecordDecl::conversion_iterator ConvE = Record->conversion_end();
|
|
|
|
if (ConvI != ConvE) {
|
2010-03-15 17:07:48 +08:00
|
|
|
HiddenTypesBuffer = ParentHiddenTypes;
|
|
|
|
HiddenTypes = &HiddenTypesBuffer;
|
|
|
|
|
2012-11-28 11:56:09 +08:00
|
|
|
for (CXXRecordDecl::conversion_iterator I = ConvI; I != ConvE; ++I) {
|
2012-05-06 08:04:32 +08:00
|
|
|
CanQualType ConvType(GetConversionType(Context, I.getDecl()));
|
|
|
|
bool Hidden = ParentHiddenTypes.count(ConvType);
|
|
|
|
if (!Hidden)
|
|
|
|
HiddenTypesBuffer.insert(ConvType);
|
2010-03-15 17:07:48 +08:00
|
|
|
|
|
|
|
// If this conversion is hidden and we're in a virtual base,
|
|
|
|
// remember that it's hidden along some inheritance path.
|
|
|
|
if (Hidden && InVirtual)
|
|
|
|
HiddenVBaseCs.insert(cast<NamedDecl>(I.getDecl()->getCanonicalDecl()));
|
|
|
|
|
|
|
|
// If this conversion isn't hidden, add it to the appropriate output.
|
|
|
|
else if (!Hidden) {
|
|
|
|
AccessSpecifier IAccess
|
|
|
|
= CXXRecordDecl::MergeAccess(Access, I.getAccess());
|
|
|
|
|
|
|
|
if (InVirtual)
|
|
|
|
VOutput.addDecl(I.getDecl(), IAccess);
|
2009-09-13 02:26:03 +08:00
|
|
|
else
|
2012-11-28 11:56:16 +08:00
|
|
|
Output.addDecl(Context, I.getDecl(), IAccess);
|
2009-09-12 05:44:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-10-26 01:03:50 +08:00
|
|
|
|
2010-03-15 17:07:48 +08:00
|
|
|
// Collect information recursively from any base classes.
|
2014-03-13 23:41:46 +08:00
|
|
|
for (const auto &I : Record->bases()) {
|
2019-12-24 18:09:24 +08:00
|
|
|
const auto *RT = I.getType()->getAs<RecordType>();
|
2010-03-15 17:07:48 +08:00
|
|
|
if (!RT) continue;
|
2009-10-26 01:03:50 +08:00
|
|
|
|
2010-03-15 17:07:48 +08:00
|
|
|
AccessSpecifier BaseAccess
|
2014-03-13 23:41:46 +08:00
|
|
|
= CXXRecordDecl::MergeAccess(Access, I.getAccessSpecifier());
|
|
|
|
bool BaseInVirtual = InVirtual || I.isVirtual();
|
2009-10-26 01:03:50 +08:00
|
|
|
|
2018-04-03 08:11:50 +08:00
|
|
|
auto *Base = cast<CXXRecordDecl>(RT->getDecl());
|
2010-03-15 17:07:48 +08:00
|
|
|
CollectVisibleConversions(Context, Base, BaseInVirtual, BaseAccess,
|
|
|
|
*HiddenTypes, Output, VOutput, HiddenVBaseCs);
|
2009-09-12 05:44:33 +08:00
|
|
|
}
|
2010-03-15 17:07:48 +08:00
|
|
|
}
|
2009-10-26 01:03:50 +08:00
|
|
|
|
2010-03-15 17:07:48 +08:00
|
|
|
/// Collect the visible conversions of a class.
|
|
|
|
///
|
|
|
|
/// This would be extremely straightforward if it weren't for virtual
|
|
|
|
/// bases. It might be worth special-casing that, really.
|
|
|
|
static void CollectVisibleConversions(ASTContext &Context,
|
2019-12-24 18:09:24 +08:00
|
|
|
const CXXRecordDecl *Record,
|
2012-11-28 11:56:16 +08:00
|
|
|
ASTUnresolvedSet &Output) {
|
2010-03-15 17:07:48 +08:00
|
|
|
// The collection of all conversions in virtual bases that we've
|
|
|
|
// found. These will be added to the output as long as they don't
|
|
|
|
// appear in the hidden-conversions set.
|
|
|
|
UnresolvedSet<8> VBaseCs;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-03-15 17:07:48 +08:00
|
|
|
// The set of conversions in virtual bases that we've determined to
|
|
|
|
// be hidden.
|
|
|
|
llvm::SmallPtrSet<NamedDecl*, 8> HiddenVBaseCs;
|
|
|
|
|
|
|
|
// The set of types hidden by classes derived from this one.
|
|
|
|
llvm::SmallPtrSet<CanQualType, 8> HiddenTypes;
|
|
|
|
|
|
|
|
// Go ahead and collect the direct conversions and add them to the
|
|
|
|
// hidden-types set.
|
2012-11-28 11:56:09 +08:00
|
|
|
CXXRecordDecl::conversion_iterator ConvI = Record->conversion_begin();
|
|
|
|
CXXRecordDecl::conversion_iterator ConvE = Record->conversion_end();
|
2012-11-28 11:56:16 +08:00
|
|
|
Output.append(Context, ConvI, ConvE);
|
2012-11-28 11:56:09 +08:00
|
|
|
for (; ConvI != ConvE; ++ConvI)
|
|
|
|
HiddenTypes.insert(GetConversionType(Context, ConvI.getDecl()));
|
2010-03-15 17:07:48 +08:00
|
|
|
|
|
|
|
// Recursively collect conversions from base classes.
|
2014-03-13 23:41:46 +08:00
|
|
|
for (const auto &I : Record->bases()) {
|
2019-12-24 18:09:24 +08:00
|
|
|
const auto *RT = I.getType()->getAs<RecordType>();
|
2010-03-15 17:07:48 +08:00
|
|
|
if (!RT) continue;
|
|
|
|
|
|
|
|
CollectVisibleConversions(Context, cast<CXXRecordDecl>(RT->getDecl()),
|
2014-03-13 23:41:46 +08:00
|
|
|
I.isVirtual(), I.getAccessSpecifier(),
|
2010-03-15 17:07:48 +08:00
|
|
|
HiddenTypes, Output, VBaseCs, HiddenVBaseCs);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add any unhidden conversions provided by virtual bases.
|
|
|
|
for (UnresolvedSetIterator I = VBaseCs.begin(), E = VBaseCs.end();
|
|
|
|
I != E; ++I) {
|
|
|
|
if (!HiddenVBaseCs.count(cast<NamedDecl>(I.getDecl()->getCanonicalDecl())))
|
2012-11-28 11:56:16 +08:00
|
|
|
Output.addDecl(Context, I.getDecl(), I.getAccess());
|
2009-09-12 05:44:33 +08:00
|
|
|
}
|
2009-09-13 02:26:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// getVisibleConversionFunctions - get all conversion functions visible
|
|
|
|
/// in current class; including conversion function templates.
|
2015-02-07 01:25:10 +08:00
|
|
|
llvm::iterator_range<CXXRecordDecl::conversion_iterator>
|
2019-12-24 18:09:24 +08:00
|
|
|
CXXRecordDecl::getVisibleConversionFunctions() const {
|
2013-08-30 12:46:40 +08:00
|
|
|
ASTContext &Ctx = getASTContext();
|
|
|
|
|
|
|
|
ASTUnresolvedSet *Set;
|
|
|
|
if (bases_begin() == bases_end()) {
|
|
|
|
// If root class, all conversions are visible.
|
|
|
|
Set = &data().Conversions.get(Ctx);
|
|
|
|
} else {
|
|
|
|
Set = &data().VisibleConversions.get(Ctx);
|
|
|
|
// If visible conversion list is not evaluated, evaluate it.
|
|
|
|
if (!data().ComputedVisibleConversions) {
|
|
|
|
CollectVisibleConversions(Ctx, this, *Set);
|
|
|
|
data().ComputedVisibleConversions = true;
|
|
|
|
}
|
2012-11-28 11:56:09 +08:00
|
|
|
}
|
2015-02-07 01:25:10 +08:00
|
|
|
return llvm::make_range(Set->begin(), Set->end());
|
2009-09-12 05:44:33 +08:00
|
|
|
}
|
|
|
|
|
2010-03-31 09:36:47 +08:00
|
|
|
void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) {
|
|
|
|
// This operation is O(N) but extremely rare. Sema only uses it to
|
|
|
|
// remove UsingShadowDecls in a class that were followed by a direct
|
|
|
|
// declaration, e.g.:
|
|
|
|
// class A : B {
|
|
|
|
// using B::operator int;
|
|
|
|
// operator int();
|
|
|
|
// };
|
|
|
|
// This is uncommon by itself and even more uncommon in conjunction
|
|
|
|
// with sufficiently large numbers of directly-declared conversions
|
|
|
|
// that asymptotic behavior matters.
|
|
|
|
|
2013-08-30 12:46:40 +08:00
|
|
|
ASTUnresolvedSet &Convs = data().Conversions.get(getASTContext());
|
2010-03-31 09:36:47 +08:00
|
|
|
for (unsigned I = 0, E = Convs.size(); I != E; ++I) {
|
|
|
|
if (Convs[I].getDecl() == ConvDecl) {
|
|
|
|
Convs.erase(I);
|
2019-03-31 16:48:19 +08:00
|
|
|
assert(llvm::find(Convs, ConvDecl) == Convs.end() &&
|
|
|
|
"conversion was found multiple times in unresolved set");
|
2010-03-31 09:36:47 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2008-11-08 04:08:42 +08:00
|
|
|
|
2010-03-31 09:36:47 +08:00
|
|
|
llvm_unreachable("conversion not found in set!");
|
2009-08-22 07:19:43 +08:00
|
|
|
}
|
2009-06-20 03:55:27 +08:00
|
|
|
|
2009-10-08 23:14:33 +08:00
|
|
|
CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const {
|
2009-10-13 04:18:28 +08:00
|
|
|
if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo())
|
2009-10-08 23:14:33 +08:00
|
|
|
return cast<CXXRecordDecl>(MSInfo->getInstantiatedFrom());
|
2014-05-12 13:36:57 +08:00
|
|
|
|
|
|
|
return nullptr;
|
2009-10-08 23:14:33 +08:00
|
|
|
}
|
|
|
|
|
2015-12-30 11:24:14 +08:00
|
|
|
MemberSpecializationInfo *CXXRecordDecl::getMemberSpecializationInfo() const {
|
|
|
|
return TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>();
|
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
void
|
2009-10-08 23:14:33 +08:00
|
|
|
CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD,
|
|
|
|
TemplateSpecializationKind TSK) {
|
2018-07-31 03:24:48 +08:00
|
|
|
assert(TemplateOrInstantiation.isNull() &&
|
2009-10-08 23:14:33 +08:00
|
|
|
"Previous template or instantiation?");
|
2013-12-14 09:04:22 +08:00
|
|
|
assert(!isa<ClassTemplatePartialSpecializationDecl>(this));
|
2018-07-31 03:24:48 +08:00
|
|
|
TemplateOrInstantiation
|
2009-10-08 23:14:33 +08:00
|
|
|
= new (getASTContext()) MemberSpecializationInfo(RD, TSK);
|
|
|
|
}
|
|
|
|
|
2015-12-30 11:24:14 +08:00
|
|
|
ClassTemplateDecl *CXXRecordDecl::getDescribedClassTemplate() const {
|
|
|
|
return TemplateOrInstantiation.dyn_cast<ClassTemplateDecl *>();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXRecordDecl::setDescribedClassTemplate(ClassTemplateDecl *Template) {
|
|
|
|
TemplateOrInstantiation = Template;
|
|
|
|
}
|
|
|
|
|
2009-12-07 14:33:48 +08:00
|
|
|
TemplateSpecializationKind CXXRecordDecl::getTemplateSpecializationKind() const{
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(this))
|
2009-10-08 23:14:33 +08:00
|
|
|
return Spec->getSpecializationKind();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-10-13 04:18:28 +08:00
|
|
|
if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo())
|
2009-10-08 23:14:33 +08:00
|
|
|
return MSInfo->getTemplateSpecializationKind();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-10-08 23:14:33 +08:00
|
|
|
return TSK_Undeclared;
|
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
void
|
2009-10-08 23:14:33 +08:00
|
|
|
CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
|
2018-04-03 08:11:50 +08:00
|
|
|
if (auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
|
2009-10-08 23:14:33 +08:00
|
|
|
Spec->setSpecializationKind(TSK);
|
|
|
|
return;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-10-13 04:18:28 +08:00
|
|
|
if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
|
2009-10-08 23:14:33 +08:00
|
|
|
MSInfo->setTemplateSpecializationKind(TSK);
|
|
|
|
return;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Not a class template or member class specialization");
|
2009-10-08 23:14:33 +08:00
|
|
|
}
|
|
|
|
|
2014-10-15 04:28:40 +08:00
|
|
|
const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
|
2017-04-21 09:15:13 +08:00
|
|
|
auto GetDefinitionOrSelf =
|
|
|
|
[](const CXXRecordDecl *D) -> const CXXRecordDecl * {
|
|
|
|
if (auto *Def = D->getDefinition())
|
|
|
|
return Def;
|
|
|
|
return D;
|
|
|
|
};
|
|
|
|
|
2014-10-15 04:28:40 +08:00
|
|
|
// If it's a class template specialization, find the template or partial
|
|
|
|
// specialization from which it was instantiated.
|
|
|
|
if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
|
|
|
|
auto From = TD->getInstantiatedFrom();
|
|
|
|
if (auto *CTD = From.dyn_cast<ClassTemplateDecl *>()) {
|
|
|
|
while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
|
|
|
|
if (NewCTD->isMemberSpecialization())
|
|
|
|
break;
|
|
|
|
CTD = NewCTD;
|
|
|
|
}
|
2017-04-21 09:15:13 +08:00
|
|
|
return GetDefinitionOrSelf(CTD->getTemplatedDecl());
|
2014-10-15 04:28:40 +08:00
|
|
|
}
|
|
|
|
if (auto *CTPSD =
|
|
|
|
From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
|
|
|
|
while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
|
|
|
|
if (NewCTPSD->isMemberSpecialization())
|
|
|
|
break;
|
|
|
|
CTPSD = NewCTPSD;
|
|
|
|
}
|
2017-04-21 09:15:13 +08:00
|
|
|
return GetDefinitionOrSelf(CTPSD);
|
2014-10-15 04:28:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
|
|
|
|
if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) {
|
|
|
|
const CXXRecordDecl *RD = this;
|
|
|
|
while (auto *NewRD = RD->getInstantiatedFromMemberClass())
|
|
|
|
RD = NewRD;
|
2017-04-21 09:15:13 +08:00
|
|
|
return GetDefinitionOrSelf(RD);
|
2014-10-15 04:28:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(!isTemplateInstantiation(this->getTemplateSpecializationKind()) &&
|
|
|
|
"couldn't find pattern for class template instantiation");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2010-07-01 22:13:13 +08:00
|
|
|
CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
|
|
|
|
ASTContext &Context = getASTContext();
|
2009-05-30 05:03:38 +08:00
|
|
|
QualType ClassType = Context.getTypeDeclType(this);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
DeclarationName Name
|
2009-08-05 13:36:45 +08:00
|
|
|
= Context.DeclarationNames.getCXXDestructorName(
|
|
|
|
Context.getCanonicalType(ClassType));
|
2009-05-30 05:03:38 +08:00
|
|
|
|
2015-02-21 10:45:19 +08:00
|
|
|
DeclContext::lookup_result R = lookup(Name);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2017-07-01 06:43:54 +08:00
|
|
|
return R.empty() ? nullptr : dyn_cast<CXXDestructorDecl>(R.front());
|
2009-05-30 05:03:38 +08:00
|
|
|
}
|
|
|
|
|
2015-05-28 08:14:02 +08:00
|
|
|
bool CXXRecordDecl::isAnyDestructorNoReturn() const {
|
|
|
|
// Destructor is noreturn.
|
|
|
|
if (const CXXDestructorDecl *Destructor = getDestructor())
|
|
|
|
if (Destructor->isNoReturn())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Check base classes destructor for noreturn.
|
|
|
|
for (const auto &Base : bases())
|
2017-05-12 19:24:25 +08:00
|
|
|
if (const CXXRecordDecl *RD = Base.getType()->getAsCXXRecordDecl())
|
|
|
|
if (RD->isAnyDestructorNoReturn())
|
|
|
|
return true;
|
2015-05-28 08:14:02 +08:00
|
|
|
|
|
|
|
// Check fields for noreturn.
|
|
|
|
for (const auto *Field : fields())
|
|
|
|
if (const CXXRecordDecl *RD =
|
|
|
|
Field->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl())
|
|
|
|
if (RD->isAnyDestructorNoReturn())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// All destructors are not noreturn.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-09-30 05:06:00 +08:00
|
|
|
static bool isDeclContextInNamespace(const DeclContext *DC) {
|
|
|
|
while (!DC->isTranslationUnit()) {
|
|
|
|
if (DC->isNamespace())
|
|
|
|
return true;
|
|
|
|
DC = DC->getParent();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-09-16 00:03:35 +08:00
|
|
|
bool CXXRecordDecl::isInterfaceLike() const {
|
|
|
|
assert(hasDefinition() && "checking for interface-like without a definition");
|
|
|
|
// All __interfaces are inheritently interface-like.
|
|
|
|
if (isInterface())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Interface-like types cannot have a user declared constructor, destructor,
|
|
|
|
// friends, VBases, conversion functions, or fields. Additionally, lambdas
|
|
|
|
// cannot be interface types.
|
|
|
|
if (isLambda() || hasUserDeclaredConstructor() ||
|
|
|
|
hasUserDeclaredDestructor() || !field_empty() || hasFriends() ||
|
|
|
|
getNumVBases() > 0 || conversion_end() - conversion_begin() > 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// No interface-like type can have a method with a definition.
|
|
|
|
for (const auto *const Method : methods())
|
2017-09-30 05:06:00 +08:00
|
|
|
if (Method->isDefined() && !Method->isImplicit())
|
2017-09-16 00:03:35 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Check "Special" types.
|
|
|
|
const auto *Uuid = getAttr<UuidAttr>();
|
2017-09-30 05:06:00 +08:00
|
|
|
// MS SDK declares IUnknown/IDispatch both in the root of a TU, or in an
|
|
|
|
// extern C++ block directly in the TU. These are only valid if in one
|
|
|
|
// of these two situations.
|
|
|
|
if (Uuid && isStruct() && !getDeclContext()->isExternCContext() &&
|
|
|
|
!isDeclContextInNamespace(getDeclContext()) &&
|
2017-09-16 00:03:35 +08:00
|
|
|
((getName() == "IUnknown" &&
|
|
|
|
Uuid->getGuid() == "00000000-0000-0000-C000-000000000046") ||
|
|
|
|
(getName() == "IDispatch" &&
|
|
|
|
Uuid->getGuid() == "00020400-0000-0000-C000-000000000046"))) {
|
|
|
|
if (getNumBases() > 0)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Any access specifiers is supposed to make this no longer interface
|
|
|
|
// like.
|
|
|
|
|
|
|
|
// If this isn't a 'special' type, it must have a single interface-like base.
|
|
|
|
if (getNumBases() != 1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const auto BaseSpec = *bases_begin();
|
|
|
|
if (BaseSpec.isVirtual() || BaseSpec.getAccessSpecifier() != AS_public)
|
|
|
|
return false;
|
|
|
|
const auto *Base = BaseSpec.getType()->getAsCXXRecordDecl();
|
|
|
|
if (Base->isInterface() || !Base->isInterfaceLike())
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-02-20 02:51:44 +08:00
|
|
|
void CXXRecordDecl::completeDefinition() {
|
2014-05-12 13:36:57 +08:00
|
|
|
completeDefinition(nullptr);
|
2011-02-20 02:51:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
|
|
|
|
RecordDecl::completeDefinition();
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
|
2010-09-29 08:15:42 +08:00
|
|
|
// If the class may be abstract (but hasn't been marked as such), check for
|
|
|
|
// any pure final overriders.
|
|
|
|
if (mayBeAbstract()) {
|
|
|
|
CXXFinalOverriderMap MyFinalOverriders;
|
|
|
|
if (!FinalOverriders) {
|
|
|
|
getFinalOverriders(MyFinalOverriders);
|
|
|
|
FinalOverriders = &MyFinalOverriders;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-09-29 08:15:42 +08:00
|
|
|
bool Done = false;
|
2018-07-31 03:24:48 +08:00
|
|
|
for (CXXFinalOverriderMap::iterator M = FinalOverriders->begin(),
|
2010-09-29 08:15:42 +08:00
|
|
|
MEnd = FinalOverriders->end();
|
|
|
|
M != MEnd && !Done; ++M) {
|
2018-07-31 03:24:48 +08:00
|
|
|
for (OverridingMethods::iterator SO = M->second.begin(),
|
2010-09-29 08:15:42 +08:00
|
|
|
SOEnd = M->second.end();
|
|
|
|
SO != SOEnd && !Done; ++SO) {
|
2018-07-31 03:24:48 +08:00
|
|
|
assert(SO->second.size() > 0 &&
|
2018-04-06 23:14:32 +08:00
|
|
|
"All virtual functions have overriding virtual functions");
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-09-29 08:15:42 +08:00
|
|
|
// C++ [class.abstract]p4:
|
|
|
|
// A class is abstract if it contains or inherits at least one
|
|
|
|
// pure virtual function for which the final overrider is pure
|
|
|
|
// virtual.
|
|
|
|
if (SO->second.front().Method->isPure()) {
|
|
|
|
data().Abstract = true;
|
|
|
|
Done = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-09-29 12:25:11 +08:00
|
|
|
// Set access bits correctly on the directly-declared conversions.
|
2013-08-30 12:46:40 +08:00
|
|
|
for (conversion_iterator I = conversion_begin(), E = conversion_end();
|
2010-09-29 12:25:11 +08:00
|
|
|
I != E; ++I)
|
2012-11-28 11:56:16 +08:00
|
|
|
I.setAccess((*I)->getAccess());
|
2010-09-29 08:15:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CXXRecordDecl::mayBeAbstract() const {
|
|
|
|
if (data().Abstract || isInvalidDecl() || !data().Polymorphic ||
|
|
|
|
isDependentContext())
|
|
|
|
return false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2014-03-13 23:41:46 +08:00
|
|
|
for (const auto &B : bases()) {
|
2018-04-03 08:11:50 +08:00
|
|
|
const auto *BaseDecl =
|
2019-10-03 19:22:48 +08:00
|
|
|
cast<CXXRecordDecl>(B.getType()->castAs<RecordType>()->getDecl());
|
2010-09-29 08:15:42 +08:00
|
|
|
if (BaseDecl->isAbstract())
|
|
|
|
return true;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-09-29 08:15:42 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-02-01 11:06:21 +08:00
|
|
|
bool CXXRecordDecl::isEffectivelyFinal() const {
|
|
|
|
auto *Def = getDefinition();
|
|
|
|
if (!Def)
|
|
|
|
return false;
|
|
|
|
if (Def->hasAttr<FinalAttr>())
|
|
|
|
return true;
|
|
|
|
if (const auto *Dtor = Def->getDestructor())
|
|
|
|
if (Dtor->hasAttr<FinalAttr>())
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void CXXDeductionGuideDecl::anchor() {}
|
2017-02-18 04:05:37 +08:00
|
|
|
|
2019-05-09 11:59:21 +08:00
|
|
|
bool ExplicitSpecifier::isEquivalent(const ExplicitSpecifier Other) const {
|
|
|
|
if ((getKind() != Other.getKind() ||
|
|
|
|
getKind() == ExplicitSpecKind::Unresolved)) {
|
|
|
|
if (getKind() == ExplicitSpecKind::Unresolved &&
|
|
|
|
Other.getKind() == ExplicitSpecKind::Unresolved) {
|
|
|
|
ODRHash SelfHash, OtherHash;
|
|
|
|
SelfHash.AddStmt(getExpr());
|
|
|
|
OtherHash.AddStmt(Other.getExpr());
|
|
|
|
return SelfHash.CalculateHash() == OtherHash.CalculateHash();
|
|
|
|
} else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExplicitSpecifier ExplicitSpecifier::getFromDecl(FunctionDecl *Function) {
|
|
|
|
switch (Function->getDeclKind()) {
|
|
|
|
case Decl::Kind::CXXConstructor:
|
|
|
|
return cast<CXXConstructorDecl>(Function)->getExplicitSpecifier();
|
|
|
|
case Decl::Kind::CXXConversion:
|
|
|
|
return cast<CXXConversionDecl>(Function)->getExplicitSpecifier();
|
|
|
|
case Decl::Kind::CXXDeductionGuide:
|
|
|
|
return cast<CXXDeductionGuideDecl>(Function)->getExplicitSpecifier();
|
|
|
|
default:
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-18 04:05:37 +08:00
|
|
|
CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create(
|
2019-05-09 11:59:21 +08:00
|
|
|
ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
|
|
|
ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T,
|
|
|
|
TypeSourceInfo *TInfo, SourceLocation EndLocation) {
|
|
|
|
return new (C, DC) CXXDeductionGuideDecl(C, DC, StartLoc, ES, NameInfo, T,
|
|
|
|
TInfo, EndLocation);
|
2017-02-18 04:05:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
2019-05-09 11:59:21 +08:00
|
|
|
return new (C, ID) CXXDeductionGuideDecl(
|
|
|
|
C, nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(),
|
|
|
|
QualType(), nullptr, SourceLocation());
|
2017-02-18 04:05:37 +08:00
|
|
|
}
|
|
|
|
|
2020-01-18 15:11:43 +08:00
|
|
|
RequiresExprBodyDecl *RequiresExprBodyDecl::Create(
|
|
|
|
ASTContext &C, DeclContext *DC, SourceLocation StartLoc) {
|
|
|
|
return new (C, DC) RequiresExprBodyDecl(C, DC, StartLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
RequiresExprBodyDecl *RequiresExprBodyDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
|
|
|
return new (C, ID) RequiresExprBodyDecl(C, nullptr, SourceLocation());
|
|
|
|
}
|
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void CXXMethodDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
2013-04-04 03:27:57 +08:00
|
|
|
bool CXXMethodDecl::isStatic() const {
|
2013-04-15 20:38:20 +08:00
|
|
|
const CXXMethodDecl *MD = getCanonicalDecl();
|
2013-04-04 03:27:57 +08:00
|
|
|
|
|
|
|
if (MD->getStorageClass() == SC_Static)
|
|
|
|
return true;
|
|
|
|
|
2013-10-08 08:58:57 +08:00
|
|
|
OverloadedOperatorKind OOK = getDeclName().getCXXOverloadedOperator();
|
|
|
|
return isStaticOverloadedOperator(OOK);
|
2013-04-04 03:27:57 +08:00
|
|
|
}
|
|
|
|
|
2012-06-27 01:45:31 +08:00
|
|
|
static bool recursivelyOverrides(const CXXMethodDecl *DerivedMD,
|
|
|
|
const CXXMethodDecl *BaseMD) {
|
2017-12-18 07:52:45 +08:00
|
|
|
for (const CXXMethodDecl *MD : DerivedMD->overridden_methods()) {
|
2012-06-27 01:45:31 +08:00
|
|
|
if (MD->getCanonicalDecl() == BaseMD->getCanonicalDecl())
|
|
|
|
return true;
|
|
|
|
if (recursivelyOverrides(MD, BaseMD))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
CXXMethodDecl *
|
2019-05-14 07:35:21 +08:00
|
|
|
CXXMethodDecl::getCorrespondingMethodDeclaredInClass(const CXXRecordDecl *RD,
|
|
|
|
bool MayBeBase) {
|
2012-06-27 01:45:31 +08:00
|
|
|
if (this->getParent()->getCanonicalDecl() == RD->getCanonicalDecl())
|
|
|
|
return this;
|
|
|
|
|
|
|
|
// Lookup doesn't work for destructors, so handle them separately.
|
|
|
|
if (isa<CXXDestructorDecl>(this)) {
|
|
|
|
CXXMethodDecl *MD = RD->getDestructor();
|
2012-08-16 04:07:17 +08:00
|
|
|
if (MD) {
|
|
|
|
if (recursivelyOverrides(MD, this))
|
|
|
|
return MD;
|
|
|
|
if (MayBeBase && recursivelyOverrides(this, MD))
|
|
|
|
return MD;
|
|
|
|
}
|
2014-05-12 13:36:57 +08:00
|
|
|
return nullptr;
|
2012-06-27 01:45:31 +08:00
|
|
|
}
|
|
|
|
|
2015-02-21 10:31:57 +08:00
|
|
|
for (auto *ND : RD->lookup(getDeclName())) {
|
2018-04-03 08:11:50 +08:00
|
|
|
auto *MD = dyn_cast<CXXMethodDecl>(ND);
|
2012-06-27 01:45:31 +08:00
|
|
|
if (!MD)
|
|
|
|
continue;
|
|
|
|
if (recursivelyOverrides(MD, this))
|
|
|
|
return MD;
|
2012-08-16 04:07:17 +08:00
|
|
|
if (MayBeBase && recursivelyOverrides(this, MD))
|
|
|
|
return MD;
|
2012-06-27 01:45:31 +08:00
|
|
|
}
|
|
|
|
|
2019-05-14 07:35:21 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
CXXMethodDecl *
|
|
|
|
CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD,
|
|
|
|
bool MayBeBase) {
|
|
|
|
if (auto *MD = getCorrespondingMethodDeclaredInClass(RD, MayBeBase))
|
|
|
|
return MD;
|
|
|
|
|
2020-02-01 09:05:27 +08:00
|
|
|
llvm::SmallVector<CXXMethodDecl*, 4> FinalOverriders;
|
|
|
|
auto AddFinalOverrider = [&](CXXMethodDecl *D) {
|
|
|
|
// If this function is overridden by a candidate final overrider, it is not
|
|
|
|
// a final overrider.
|
|
|
|
for (CXXMethodDecl *OtherD : FinalOverriders) {
|
|
|
|
if (declaresSameEntity(D, OtherD) || recursivelyOverrides(OtherD, D))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Other candidate final overriders might be overridden by this function.
|
|
|
|
FinalOverriders.erase(
|
|
|
|
std::remove_if(FinalOverriders.begin(), FinalOverriders.end(),
|
|
|
|
[&](CXXMethodDecl *OtherD) {
|
|
|
|
return recursivelyOverrides(D, OtherD);
|
|
|
|
}),
|
|
|
|
FinalOverriders.end());
|
|
|
|
|
|
|
|
FinalOverriders.push_back(D);
|
|
|
|
};
|
|
|
|
|
2014-03-13 23:41:46 +08:00
|
|
|
for (const auto &I : RD->bases()) {
|
|
|
|
const RecordType *RT = I.getType()->getAs<RecordType>();
|
2012-06-27 01:45:31 +08:00
|
|
|
if (!RT)
|
|
|
|
continue;
|
2018-04-03 08:11:50 +08:00
|
|
|
const auto *Base = cast<CXXRecordDecl>(RT->getDecl());
|
2020-02-01 09:05:27 +08:00
|
|
|
if (CXXMethodDecl *D = this->getCorrespondingMethodInClass(Base))
|
|
|
|
AddFinalOverrider(D);
|
2012-06-27 01:45:31 +08:00
|
|
|
}
|
|
|
|
|
2020-02-01 09:05:27 +08:00
|
|
|
return FinalOverriders.size() == 1 ? FinalOverriders.front() : nullptr;
|
2012-06-27 01:45:31 +08:00
|
|
|
}
|
|
|
|
|
2019-06-14 16:56:20 +08:00
|
|
|
CXXMethodDecl *CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
|
|
|
SourceLocation StartLoc,
|
|
|
|
const DeclarationNameInfo &NameInfo,
|
|
|
|
QualType T, TypeSourceInfo *TInfo,
|
|
|
|
StorageClass SC, bool isInline,
|
|
|
|
ConstexprSpecKind ConstexprKind,
|
2020-01-09 21:07:51 +08:00
|
|
|
SourceLocation EndLocation,
|
|
|
|
Expr *TrailingRequiresClause) {
|
2019-06-14 16:56:20 +08:00
|
|
|
return new (C, RD)
|
|
|
|
CXXMethodDecl(CXXMethod, C, RD, StartLoc, NameInfo, T, TInfo, SC,
|
2020-01-09 21:07:51 +08:00
|
|
|
isInline, ConstexprKind, EndLocation,
|
|
|
|
TrailingRequiresClause);
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2019-06-14 16:56:20 +08:00
|
|
|
return new (C, ID) CXXMethodDecl(
|
|
|
|
CXXMethod, C, nullptr, SourceLocation(), DeclarationNameInfo(),
|
2020-01-09 21:07:51 +08:00
|
|
|
QualType(), nullptr, SC_None, false, CSK_unspecified, SourceLocation(),
|
|
|
|
nullptr);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2017-07-13 14:08:27 +08:00
|
|
|
CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
|
|
|
|
bool IsAppleKext) {
|
|
|
|
assert(isVirtual() && "this method is expected to be virtual");
|
|
|
|
|
|
|
|
// When building with -fapple-kext, all calls must go through the vtable since
|
|
|
|
// the kernel linker can do runtime patching of vtables.
|
|
|
|
if (IsAppleKext)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
// If the member function is marked 'final', we know that it can't be
|
|
|
|
// overridden and can therefore devirtualize it unless it's pure virtual.
|
|
|
|
if (hasAttr<FinalAttr>())
|
|
|
|
return isPure() ? nullptr : this;
|
|
|
|
|
|
|
|
// If Base is unknown, we cannot devirtualize.
|
|
|
|
if (!Base)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
// If the base expression (after skipping derived-to-base conversions) is a
|
|
|
|
// class prvalue, then we can devirtualize.
|
|
|
|
Base = Base->getBestDynamicClassTypeExpr();
|
|
|
|
if (Base->isRValue() && Base->getType()->isRecordType())
|
|
|
|
return this;
|
|
|
|
|
|
|
|
// If we don't even know what we would call, we can't devirtualize.
|
|
|
|
const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType();
|
|
|
|
if (!BestDynamicDecl)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
// There may be a method corresponding to MD in a derived class.
|
|
|
|
CXXMethodDecl *DevirtualizedMethod =
|
|
|
|
getCorrespondingMethodInClass(BestDynamicDecl);
|
|
|
|
|
2020-02-01 09:05:27 +08:00
|
|
|
// If there final overrider in the dynamic type is ambiguous, we can't
|
|
|
|
// devirtualize this call.
|
|
|
|
if (!DevirtualizedMethod)
|
|
|
|
return nullptr;
|
|
|
|
|
2017-07-13 14:08:27 +08:00
|
|
|
// If that method is pure virtual, we can't devirtualize. If this code is
|
|
|
|
// reached, the result would be UB, not a direct call to the derived class
|
|
|
|
// function, and we can't assume the derived class function is defined.
|
|
|
|
if (DevirtualizedMethod->isPure())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
// If that method is marked final, we can devirtualize it.
|
|
|
|
if (DevirtualizedMethod->hasAttr<FinalAttr>())
|
|
|
|
return DevirtualizedMethod;
|
|
|
|
|
2019-09-01 02:52:44 +08:00
|
|
|
// Similarly, if the class itself or its destructor is marked 'final',
|
2020-02-18 10:48:38 +08:00
|
|
|
// the class can't be derived from and we can therefore devirtualize the
|
2019-09-01 02:52:44 +08:00
|
|
|
// member function call.
|
2020-02-01 11:06:21 +08:00
|
|
|
if (BestDynamicDecl->isEffectivelyFinal())
|
2017-07-13 14:08:27 +08:00
|
|
|
return DevirtualizedMethod;
|
|
|
|
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
|
|
|
|
if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
|
2017-07-13 14:08:27 +08:00
|
|
|
if (VD->getType()->isRecordType())
|
|
|
|
// This is a record decl. We know the type and can devirtualize it.
|
|
|
|
return DevirtualizedMethod;
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We can devirtualize calls on an object accessed by a class member access
|
|
|
|
// expression, since by C++11 [basic.life]p6 we know that it can't refer to
|
|
|
|
// a derived class object constructed in the same location.
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *ME = dyn_cast<MemberExpr>(Base)) {
|
2018-03-01 13:43:23 +08:00
|
|
|
const ValueDecl *VD = ME->getMemberDecl();
|
|
|
|
return VD->getType()->isRecordType() ? DevirtualizedMethod : nullptr;
|
|
|
|
}
|
2017-07-13 14:08:27 +08:00
|
|
|
|
|
|
|
// Likewise for calls on an object accessed by a (non-reference) pointer to
|
|
|
|
// member access.
|
|
|
|
if (auto *BO = dyn_cast<BinaryOperator>(Base)) {
|
|
|
|
if (BO->isPtrMemOp()) {
|
|
|
|
auto *MPT = BO->getRHS()->getType()->castAs<MemberPointerType>();
|
|
|
|
if (MPT->getPointeeType()->isRecordType())
|
|
|
|
return DevirtualizedMethod;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We can't devirtualize the call.
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-09-22 01:29:33 +08:00
|
|
|
bool CXXMethodDecl::isUsualDeallocationFunction(
|
|
|
|
SmallVectorImpl<const FunctionDecl *> &PreventedBy) const {
|
|
|
|
assert(PreventedBy.empty() && "PreventedBy is expected to be empty");
|
2009-09-30 02:16:17 +08:00
|
|
|
if (getOverloadedOperator() != OO_Delete &&
|
|
|
|
getOverloadedOperator() != OO_Array_Delete)
|
|
|
|
return false;
|
2010-02-26 13:06:18 +08:00
|
|
|
|
|
|
|
// C++ [basic.stc.dynamic.deallocation]p2:
|
|
|
|
// A template instance is never a usual deallocation function,
|
|
|
|
// regardless of its signature.
|
|
|
|
if (getPrimaryTemplate())
|
|
|
|
return false;
|
|
|
|
|
2009-09-30 02:16:17 +08:00
|
|
|
// C++ [basic.stc.dynamic.deallocation]p2:
|
2018-07-31 03:24:48 +08:00
|
|
|
// If a class T has a member deallocation function named operator delete
|
2009-09-30 02:16:17 +08:00
|
|
|
// with exactly one parameter, then that function is a usual (non-placement)
|
|
|
|
// deallocation function. [...]
|
|
|
|
if (getNumParams() == 1)
|
|
|
|
return true;
|
2016-10-11 02:54:32 +08:00
|
|
|
unsigned UsualParams = 1;
|
2016-09-30 06:49:46 +08:00
|
|
|
|
2017-10-13 09:55:36 +08:00
|
|
|
// C++ P0722:
|
|
|
|
// A destroying operator delete is a usual deallocation function if
|
|
|
|
// removing the std::destroying_delete_t parameter and changing the
|
|
|
|
// first parameter type from T* to void* results in the signature of
|
|
|
|
// a usual deallocation function.
|
|
|
|
if (isDestroyingOperatorDelete())
|
|
|
|
++UsualParams;
|
|
|
|
|
2016-10-11 02:54:32 +08:00
|
|
|
// C++ <=14 [basic.stc.dynamic.deallocation]p2:
|
2018-07-31 03:24:48 +08:00
|
|
|
// [...] If class T does not declare such an operator delete but does
|
|
|
|
// declare a member deallocation function named operator delete with
|
2009-09-30 02:16:17 +08:00
|
|
|
// exactly two parameters, the second of which has type std::size_t (18.1),
|
|
|
|
// then this function is a usual deallocation function.
|
2016-10-11 02:54:32 +08:00
|
|
|
//
|
|
|
|
// C++17 says a usual deallocation function is one with the signature
|
|
|
|
// (void* [, size_t] [, std::align_val_t] [, ...])
|
|
|
|
// and all such functions are usual deallocation functions. It's not clear
|
|
|
|
// that allowing varargs functions was intentional.
|
2009-09-30 02:16:17 +08:00
|
|
|
ASTContext &Context = getASTContext();
|
2016-10-11 02:54:32 +08:00
|
|
|
if (UsualParams < getNumParams() &&
|
|
|
|
Context.hasSameUnqualifiedType(getParamDecl(UsualParams)->getType(),
|
|
|
|
Context.getSizeType()))
|
|
|
|
++UsualParams;
|
|
|
|
|
|
|
|
if (UsualParams < getNumParams() &&
|
|
|
|
getParamDecl(UsualParams)->getType()->isAlignValT())
|
|
|
|
++UsualParams;
|
|
|
|
|
|
|
|
if (UsualParams != getNumParams())
|
2009-09-30 02:16:17 +08:00
|
|
|
return false;
|
2016-10-11 02:54:32 +08:00
|
|
|
|
|
|
|
// In C++17 onwards, all potential usual deallocation functions are actual
|
2019-02-03 11:44:31 +08:00
|
|
|
// usual deallocation functions. Honor this behavior when post-C++14
|
|
|
|
// deallocation functions are offered as extensions too.
|
|
|
|
// FIXME(EricWF): Destrying Delete should be a language option. How do we
|
|
|
|
// handle when destroying delete is used prior to C++17?
|
|
|
|
if (Context.getLangOpts().CPlusPlus17 ||
|
|
|
|
Context.getLangOpts().AlignedAllocation ||
|
|
|
|
isDestroyingOperatorDelete())
|
2016-10-11 02:54:32 +08:00
|
|
|
return true;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
|
|
|
// This function is a usual deallocation function if there are no
|
2009-09-30 02:16:17 +08:00
|
|
|
// single-parameter deallocation functions of the same kind.
|
2015-02-21 10:45:19 +08:00
|
|
|
DeclContext::lookup_result R = getDeclContext()->lookup(getDeclName());
|
2018-09-22 01:29:33 +08:00
|
|
|
bool Result = true;
|
|
|
|
for (const auto *D : R) {
|
|
|
|
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
|
|
|
|
if (FD->getNumParams() == 1) {
|
|
|
|
PreventedBy.push_back(FD);
|
|
|
|
Result = false;
|
|
|
|
}
|
|
|
|
}
|
2009-09-30 02:16:17 +08:00
|
|
|
}
|
2018-09-22 01:29:33 +08:00
|
|
|
return Result;
|
2009-09-30 02:16:17 +08:00
|
|
|
}
|
|
|
|
|
Complete reimplementation of the synthesis for implicitly-defined copy
assignment operators.
Previously, Sema provided type-checking and template instantiation for
copy assignment operators, then CodeGen would synthesize the actual
body of the copy constructor. Unfortunately, the two were not in sync,
and CodeGen might pick a copy-assignment operator that is different
from what Sema chose, leading to strange failures, e.g., link-time
failures when CodeGen called a copy-assignment operator that was not
instantiation, run-time failures when copy-assignment operators were
overloaded for const/non-const references and the wrong one was
picked, and run-time failures when by-value copy-assignment operators
did not have their arguments properly copy-initialized.
This implementation synthesizes the implicitly-defined copy assignment
operator bodies in Sema, so that the resulting ASTs encode exactly
what CodeGen needs to do; there is no longer any special code in
CodeGen to synthesize copy-assignment operators. The synthesis of the
body is relatively simple, and we generate one of three different
kinds of copy statements for each base or member:
- For a class subobject, call the appropriate copy-assignment
operator, after overload resolution has determined what that is.
- For an array of scalar types or an array of class types that have
trivial copy assignment operators, construct a call to
__builtin_memcpy.
- For an array of class types with non-trivial copy assignment
operators, synthesize a (possibly nested!) for loop whose inner
statement calls the copy constructor.
- For a scalar type, use built-in assignment.
This patch fixes at least a few tests cases in Boost.Spirit that were
failing because CodeGen picked the wrong copy-assignment operator
(leading to link-time failures), and I suspect a number of undiagnosed
problems will also go away with this change.
Some of the diagnostics we had previously have gotten worse with this
change, since we're going through generic code for our
type-checking. I will improve this in a subsequent patch.
llvm-svn: 102853
2010-05-02 04:49:11 +08:00
|
|
|
bool CXXMethodDecl::isCopyAssignmentOperator() const {
|
2011-05-26 04:50:04 +08:00
|
|
|
// C++0x [class.copy]p17:
|
2018-07-31 03:24:48 +08:00
|
|
|
// A user-declared copy assignment operator X::operator= is a non-static
|
|
|
|
// non-template member function of class X with exactly one parameter of
|
Complete reimplementation of the synthesis for implicitly-defined copy
assignment operators.
Previously, Sema provided type-checking and template instantiation for
copy assignment operators, then CodeGen would synthesize the actual
body of the copy constructor. Unfortunately, the two were not in sync,
and CodeGen might pick a copy-assignment operator that is different
from what Sema chose, leading to strange failures, e.g., link-time
failures when CodeGen called a copy-assignment operator that was not
instantiation, run-time failures when copy-assignment operators were
overloaded for const/non-const references and the wrong one was
picked, and run-time failures when by-value copy-assignment operators
did not have their arguments properly copy-initialized.
This implementation synthesizes the implicitly-defined copy assignment
operator bodies in Sema, so that the resulting ASTs encode exactly
what CodeGen needs to do; there is no longer any special code in
CodeGen to synthesize copy-assignment operators. The synthesis of the
body is relatively simple, and we generate one of three different
kinds of copy statements for each base or member:
- For a class subobject, call the appropriate copy-assignment
operator, after overload resolution has determined what that is.
- For an array of scalar types or an array of class types that have
trivial copy assignment operators, construct a call to
__builtin_memcpy.
- For an array of class types with non-trivial copy assignment
operators, synthesize a (possibly nested!) for loop whose inner
statement calls the copy constructor.
- For a scalar type, use built-in assignment.
This patch fixes at least a few tests cases in Boost.Spirit that were
failing because CodeGen picked the wrong copy-assignment operator
(leading to link-time failures), and I suspect a number of undiagnosed
problems will also go away with this change.
Some of the diagnostics we had previously have gotten worse with this
change, since we're going through generic code for our
type-checking. I will improve this in a subsequent patch.
llvm-svn: 102853
2010-05-02 04:49:11 +08:00
|
|
|
// type X, X&, const X&, volatile X& or const volatile X&.
|
|
|
|
if (/*operator=*/getOverloadedOperator() != OO_Equal ||
|
2018-07-31 03:24:48 +08:00
|
|
|
/*non-static*/ isStatic() ||
|
2013-07-12 07:55:07 +08:00
|
|
|
/*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate() ||
|
|
|
|
getNumParams() != 1)
|
Complete reimplementation of the synthesis for implicitly-defined copy
assignment operators.
Previously, Sema provided type-checking and template instantiation for
copy assignment operators, then CodeGen would synthesize the actual
body of the copy constructor. Unfortunately, the two were not in sync,
and CodeGen might pick a copy-assignment operator that is different
from what Sema chose, leading to strange failures, e.g., link-time
failures when CodeGen called a copy-assignment operator that was not
instantiation, run-time failures when copy-assignment operators were
overloaded for const/non-const references and the wrong one was
picked, and run-time failures when by-value copy-assignment operators
did not have their arguments properly copy-initialized.
This implementation synthesizes the implicitly-defined copy assignment
operator bodies in Sema, so that the resulting ASTs encode exactly
what CodeGen needs to do; there is no longer any special code in
CodeGen to synthesize copy-assignment operators. The synthesis of the
body is relatively simple, and we generate one of three different
kinds of copy statements for each base or member:
- For a class subobject, call the appropriate copy-assignment
operator, after overload resolution has determined what that is.
- For an array of scalar types or an array of class types that have
trivial copy assignment operators, construct a call to
__builtin_memcpy.
- For an array of class types with non-trivial copy assignment
operators, synthesize a (possibly nested!) for loop whose inner
statement calls the copy constructor.
- For a scalar type, use built-in assignment.
This patch fixes at least a few tests cases in Boost.Spirit that were
failing because CodeGen picked the wrong copy-assignment operator
(leading to link-time failures), and I suspect a number of undiagnosed
problems will also go away with this change.
Some of the diagnostics we had previously have gotten worse with this
change, since we're going through generic code for our
type-checking. I will improve this in a subsequent patch.
llvm-svn: 102853
2010-05-02 04:49:11 +08:00
|
|
|
return false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
Complete reimplementation of the synthesis for implicitly-defined copy
assignment operators.
Previously, Sema provided type-checking and template instantiation for
copy assignment operators, then CodeGen would synthesize the actual
body of the copy constructor. Unfortunately, the two were not in sync,
and CodeGen might pick a copy-assignment operator that is different
from what Sema chose, leading to strange failures, e.g., link-time
failures when CodeGen called a copy-assignment operator that was not
instantiation, run-time failures when copy-assignment operators were
overloaded for const/non-const references and the wrong one was
picked, and run-time failures when by-value copy-assignment operators
did not have their arguments properly copy-initialized.
This implementation synthesizes the implicitly-defined copy assignment
operator bodies in Sema, so that the resulting ASTs encode exactly
what CodeGen needs to do; there is no longer any special code in
CodeGen to synthesize copy-assignment operators. The synthesis of the
body is relatively simple, and we generate one of three different
kinds of copy statements for each base or member:
- For a class subobject, call the appropriate copy-assignment
operator, after overload resolution has determined what that is.
- For an array of scalar types or an array of class types that have
trivial copy assignment operators, construct a call to
__builtin_memcpy.
- For an array of class types with non-trivial copy assignment
operators, synthesize a (possibly nested!) for loop whose inner
statement calls the copy constructor.
- For a scalar type, use built-in assignment.
This patch fixes at least a few tests cases in Boost.Spirit that were
failing because CodeGen picked the wrong copy-assignment operator
(leading to link-time failures), and I suspect a number of undiagnosed
problems will also go away with this change.
Some of the diagnostics we had previously have gotten worse with this
change, since we're going through generic code for our
type-checking. I will improve this in a subsequent patch.
llvm-svn: 102853
2010-05-02 04:49:11 +08:00
|
|
|
QualType ParamType = getParamDecl(0)->getType();
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *Ref = ParamType->getAs<LValueReferenceType>())
|
Complete reimplementation of the synthesis for implicitly-defined copy
assignment operators.
Previously, Sema provided type-checking and template instantiation for
copy assignment operators, then CodeGen would synthesize the actual
body of the copy constructor. Unfortunately, the two were not in sync,
and CodeGen might pick a copy-assignment operator that is different
from what Sema chose, leading to strange failures, e.g., link-time
failures when CodeGen called a copy-assignment operator that was not
instantiation, run-time failures when copy-assignment operators were
overloaded for const/non-const references and the wrong one was
picked, and run-time failures when by-value copy-assignment operators
did not have their arguments properly copy-initialized.
This implementation synthesizes the implicitly-defined copy assignment
operator bodies in Sema, so that the resulting ASTs encode exactly
what CodeGen needs to do; there is no longer any special code in
CodeGen to synthesize copy-assignment operators. The synthesis of the
body is relatively simple, and we generate one of three different
kinds of copy statements for each base or member:
- For a class subobject, call the appropriate copy-assignment
operator, after overload resolution has determined what that is.
- For an array of scalar types or an array of class types that have
trivial copy assignment operators, construct a call to
__builtin_memcpy.
- For an array of class types with non-trivial copy assignment
operators, synthesize a (possibly nested!) for loop whose inner
statement calls the copy constructor.
- For a scalar type, use built-in assignment.
This patch fixes at least a few tests cases in Boost.Spirit that were
failing because CodeGen picked the wrong copy-assignment operator
(leading to link-time failures), and I suspect a number of undiagnosed
problems will also go away with this change.
Some of the diagnostics we had previously have gotten worse with this
change, since we're going through generic code for our
type-checking. I will improve this in a subsequent patch.
llvm-svn: 102853
2010-05-02 04:49:11 +08:00
|
|
|
ParamType = Ref->getPointeeType();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
Complete reimplementation of the synthesis for implicitly-defined copy
assignment operators.
Previously, Sema provided type-checking and template instantiation for
copy assignment operators, then CodeGen would synthesize the actual
body of the copy constructor. Unfortunately, the two were not in sync,
and CodeGen might pick a copy-assignment operator that is different
from what Sema chose, leading to strange failures, e.g., link-time
failures when CodeGen called a copy-assignment operator that was not
instantiation, run-time failures when copy-assignment operators were
overloaded for const/non-const references and the wrong one was
picked, and run-time failures when by-value copy-assignment operators
did not have their arguments properly copy-initialized.
This implementation synthesizes the implicitly-defined copy assignment
operator bodies in Sema, so that the resulting ASTs encode exactly
what CodeGen needs to do; there is no longer any special code in
CodeGen to synthesize copy-assignment operators. The synthesis of the
body is relatively simple, and we generate one of three different
kinds of copy statements for each base or member:
- For a class subobject, call the appropriate copy-assignment
operator, after overload resolution has determined what that is.
- For an array of scalar types or an array of class types that have
trivial copy assignment operators, construct a call to
__builtin_memcpy.
- For an array of class types with non-trivial copy assignment
operators, synthesize a (possibly nested!) for loop whose inner
statement calls the copy constructor.
- For a scalar type, use built-in assignment.
This patch fixes at least a few tests cases in Boost.Spirit that were
failing because CodeGen picked the wrong copy-assignment operator
(leading to link-time failures), and I suspect a number of undiagnosed
problems will also go away with this change.
Some of the diagnostics we had previously have gotten worse with this
change, since we're going through generic code for our
type-checking. I will improve this in a subsequent patch.
llvm-svn: 102853
2010-05-02 04:49:11 +08:00
|
|
|
ASTContext &Context = getASTContext();
|
|
|
|
QualType ClassType
|
|
|
|
= Context.getCanonicalType(Context.getTypeDeclType(getParent()));
|
|
|
|
return Context.hasSameUnqualifiedType(ClassType, ParamType);
|
|
|
|
}
|
|
|
|
|
2011-05-26 04:50:04 +08:00
|
|
|
bool CXXMethodDecl::isMoveAssignmentOperator() const {
|
|
|
|
// C++0x [class.copy]p19:
|
|
|
|
// A user-declared move assignment operator X::operator= is a non-static
|
|
|
|
// non-template member function of class X with exactly one parameter of type
|
|
|
|
// X&&, const X&&, volatile X&&, or const volatile X&&.
|
|
|
|
if (getOverloadedOperator() != OO_Equal || isStatic() ||
|
2013-07-12 07:55:07 +08:00
|
|
|
getPrimaryTemplate() || getDescribedFunctionTemplate() ||
|
|
|
|
getNumParams() != 1)
|
2011-05-26 04:50:04 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
QualType ParamType = getParamDecl(0)->getType();
|
|
|
|
if (!isa<RValueReferenceType>(ParamType))
|
|
|
|
return false;
|
|
|
|
ParamType = ParamType->getPointeeType();
|
|
|
|
|
|
|
|
ASTContext &Context = getASTContext();
|
|
|
|
QualType ClassType
|
|
|
|
= Context.getCanonicalType(Context.getTypeDeclType(getParent()));
|
|
|
|
return Context.hasSameUnqualifiedType(ClassType, ParamType);
|
|
|
|
}
|
|
|
|
|
2009-05-17 07:58:37 +08:00
|
|
|
void CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *MD) {
|
2009-12-04 13:51:56 +08:00
|
|
|
assert(MD->isCanonicalDecl() && "Method is not canonical!");
|
2010-01-31 01:42:34 +08:00
|
|
|
assert(!MD->getParent()->isDependentContext() &&
|
|
|
|
"Can't add an overridden method to a class template!");
|
2012-03-10 09:39:01 +08:00
|
|
|
assert(MD->isVirtual() && "Method is not virtual!");
|
2010-01-31 01:42:34 +08:00
|
|
|
|
2010-03-03 07:58:15 +08:00
|
|
|
getASTContext().addOverriddenMethod(this, MD);
|
2009-05-17 07:58:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CXXMethodDecl::method_iterator CXXMethodDecl::begin_overridden_methods() const {
|
2014-05-12 13:36:57 +08:00
|
|
|
if (isa<CXXConstructorDecl>(this)) return nullptr;
|
2010-03-03 07:58:15 +08:00
|
|
|
return getASTContext().overridden_methods_begin(this);
|
2009-05-17 07:58:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CXXMethodDecl::method_iterator CXXMethodDecl::end_overridden_methods() const {
|
2014-05-12 13:36:57 +08:00
|
|
|
if (isa<CXXConstructorDecl>(this)) return nullptr;
|
2010-03-03 07:58:15 +08:00
|
|
|
return getASTContext().overridden_methods_end(this);
|
2009-05-17 07:58:37 +08:00
|
|
|
}
|
|
|
|
|
2010-07-05 05:44:35 +08:00
|
|
|
unsigned CXXMethodDecl::size_overridden_methods() const {
|
2012-03-10 09:39:01 +08:00
|
|
|
if (isa<CXXConstructorDecl>(this)) return 0;
|
2010-07-05 05:44:35 +08:00
|
|
|
return getASTContext().overridden_methods_size(this);
|
|
|
|
}
|
|
|
|
|
2016-07-05 15:49:31 +08:00
|
|
|
CXXMethodDecl::overridden_method_range
|
|
|
|
CXXMethodDecl::overridden_methods() const {
|
|
|
|
if (isa<CXXConstructorDecl>(this))
|
|
|
|
return overridden_method_range(nullptr, nullptr);
|
|
|
|
return getASTContext().overridden_methods(this);
|
|
|
|
}
|
|
|
|
|
2019-07-22 17:39:13 +08:00
|
|
|
static QualType getThisObjectType(ASTContext &C, const FunctionProtoType *FPT,
|
|
|
|
const CXXRecordDecl *Decl) {
|
|
|
|
QualType ClassTy = C.getTypeDeclType(Decl);
|
|
|
|
return C.getQualifiedType(ClassTy, FPT->getMethodQuals());
|
|
|
|
}
|
|
|
|
|
2018-12-13 18:15:27 +08:00
|
|
|
QualType CXXMethodDecl::getThisType(const FunctionProtoType *FPT,
|
|
|
|
const CXXRecordDecl *Decl) {
|
|
|
|
ASTContext &C = Decl->getASTContext();
|
2019-07-22 17:39:13 +08:00
|
|
|
QualType ObjectTy = ::getThisObjectType(C, FPT, Decl);
|
|
|
|
return C.getPointerType(ObjectTy);
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType CXXMethodDecl::getThisObjectType(const FunctionProtoType *FPT,
|
|
|
|
const CXXRecordDecl *Decl) {
|
|
|
|
ASTContext &C = Decl->getASTContext();
|
|
|
|
return ::getThisObjectType(C, FPT, Decl);
|
2018-12-13 18:15:27 +08:00
|
|
|
}
|
|
|
|
|
2019-01-11 09:54:53 +08:00
|
|
|
QualType CXXMethodDecl::getThisType() const {
|
2008-10-25 06:28:18 +08:00
|
|
|
// C++ 9.3.2p1: The type of this in a member function of a class X is X*.
|
|
|
|
// If the member function is declared const, the type of this is const X*,
|
|
|
|
// if the member function is declared volatile, the type of this is
|
|
|
|
// volatile X*, and if the member function is declared const volatile,
|
|
|
|
// the type of this is const volatile X*.
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
assert(isInstance() && "No 'this' for static methods!");
|
2020-03-12 22:56:32 +08:00
|
|
|
return CXXMethodDecl::getThisType(getType()->castAs<FunctionProtoType>(),
|
2018-12-13 18:15:27 +08:00
|
|
|
getParent());
|
2019-07-22 17:39:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
QualType CXXMethodDecl::getThisObjectType() const {
|
|
|
|
// Ditto getThisType.
|
|
|
|
assert(isInstance() && "No 'this' for static methods!");
|
2020-03-12 22:56:32 +08:00
|
|
|
return CXXMethodDecl::getThisObjectType(
|
|
|
|
getType()->castAs<FunctionProtoType>(), getParent());
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
}
|
|
|
|
|
2009-12-07 04:50:05 +08:00
|
|
|
bool CXXMethodDecl::hasInlineBody() const {
|
2018-07-31 03:24:48 +08:00
|
|
|
// If this function is a template instantiation, look at the template from
|
2010-01-06 03:06:31 +08:00
|
|
|
// which it was instantiated.
|
|
|
|
const FunctionDecl *CheckFn = getTemplateInstantiationPattern();
|
|
|
|
if (!CheckFn)
|
|
|
|
CheckFn = this;
|
2017-08-12 09:46:03 +08:00
|
|
|
|
2009-12-07 04:50:05 +08:00
|
|
|
const FunctionDecl *fn;
|
2017-08-12 09:46:03 +08:00
|
|
|
return CheckFn->isDefined(fn) && !fn->isOutOfLine() &&
|
|
|
|
(fn->doesThisDeclarationHaveABody() || fn->willHaveBody());
|
2009-12-07 04:50:05 +08:00
|
|
|
}
|
|
|
|
|
2012-02-17 11:02:34 +08:00
|
|
|
bool CXXMethodDecl::isLambdaStaticInvoker() const {
|
2013-09-29 16:45:24 +08:00
|
|
|
const CXXRecordDecl *P = getParent();
|
|
|
|
if (P->isLambda()) {
|
|
|
|
if (const CXXMethodDecl *StaticInvoker = P->getLambdaStaticInvoker()) {
|
|
|
|
if (StaticInvoker == this) return true;
|
|
|
|
if (P->isGenericLambda() && this->isFunctionTemplateSpecialization())
|
|
|
|
return StaticInvoker == this->getPrimaryTemplate()->getTemplatedDecl();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2012-02-17 11:02:34 +08:00
|
|
|
}
|
|
|
|
|
2011-01-09 04:30:50 +08:00
|
|
|
CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
|
|
|
|
TypeSourceInfo *TInfo, bool IsVirtual,
|
|
|
|
SourceLocation L, Expr *Init,
|
|
|
|
SourceLocation R,
|
|
|
|
SourceLocation EllipsisLoc)
|
2017-11-15 07:13:32 +08:00
|
|
|
: Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init),
|
|
|
|
LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual),
|
|
|
|
IsWritten(false), SourceOrder(0) {}
|
2008-11-05 12:29:56 +08:00
|
|
|
|
2011-01-09 04:30:50 +08:00
|
|
|
CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
|
|
|
|
FieldDecl *Member,
|
|
|
|
SourceLocation MemberLoc,
|
|
|
|
SourceLocation L, Expr *Init,
|
|
|
|
SourceLocation R)
|
2017-11-15 07:13:32 +08:00
|
|
|
: Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
|
|
|
|
LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
|
|
|
|
IsWritten(false), SourceOrder(0) {}
|
2010-12-04 17:14:42 +08:00
|
|
|
|
2011-01-09 04:30:50 +08:00
|
|
|
CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
|
|
|
|
IndirectFieldDecl *Member,
|
|
|
|
SourceLocation MemberLoc,
|
|
|
|
SourceLocation L, Expr *Init,
|
|
|
|
SourceLocation R)
|
2017-11-15 07:13:32 +08:00
|
|
|
: Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
|
|
|
|
LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
|
|
|
|
IsWritten(false), SourceOrder(0) {}
|
2008-11-05 12:29:56 +08:00
|
|
|
|
2011-02-27 03:13:13 +08:00
|
|
|
CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
|
2011-11-01 09:16:03 +08:00
|
|
|
TypeSourceInfo *TInfo,
|
2018-07-31 03:24:48 +08:00
|
|
|
SourceLocation L, Expr *Init,
|
2011-02-27 03:13:13 +08:00
|
|
|
SourceLocation R)
|
2017-11-15 07:13:32 +08:00
|
|
|
: Initializee(TInfo), Init(Init), LParenLoc(L), RParenLoc(R),
|
|
|
|
IsDelegating(true), IsVirtual(false), IsWritten(false), SourceOrder(0) {}
|
2011-02-27 03:13:13 +08:00
|
|
|
|
2018-12-04 06:15:34 +08:00
|
|
|
int64_t CXXCtorInitializer::getID(const ASTContext &Context) const {
|
2018-12-04 06:19:05 +08:00
|
|
|
return Context.getAllocator()
|
|
|
|
.identifyKnownAlignedObject<CXXCtorInitializer>(this);
|
2018-12-04 06:15:34 +08:00
|
|
|
}
|
|
|
|
|
2011-01-09 04:30:50 +08:00
|
|
|
TypeLoc CXXCtorInitializer::getBaseClassLoc() const {
|
2009-12-03 06:36:29 +08:00
|
|
|
if (isBaseInitializer())
|
2011-01-09 07:01:16 +08:00
|
|
|
return Initializee.get<TypeSourceInfo*>()->getTypeLoc();
|
2009-12-03 06:36:29 +08:00
|
|
|
else
|
2018-04-03 08:11:50 +08:00
|
|
|
return {};
|
2009-12-03 06:36:29 +08:00
|
|
|
}
|
|
|
|
|
2011-01-09 04:30:50 +08:00
|
|
|
const Type *CXXCtorInitializer::getBaseClass() const {
|
2009-12-03 06:36:29 +08:00
|
|
|
if (isBaseInitializer())
|
2011-01-09 07:01:16 +08:00
|
|
|
return Initializee.get<TypeSourceInfo*>()->getType().getTypePtr();
|
2009-12-03 06:36:29 +08:00
|
|
|
else
|
2014-05-12 13:36:57 +08:00
|
|
|
return nullptr;
|
2009-12-03 06:36:29 +08:00
|
|
|
}
|
|
|
|
|
2011-01-09 04:30:50 +08:00
|
|
|
SourceLocation CXXCtorInitializer::getSourceLocation() const {
|
2011-06-12 01:19:42 +08:00
|
|
|
if (isInClassMemberInitializer())
|
|
|
|
return getAnyMember()->getLocation();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2015-01-18 08:12:58 +08:00
|
|
|
if (isAnyMemberInitializer())
|
|
|
|
return getMemberLocation();
|
|
|
|
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *TSInfo = Initializee.get<TypeSourceInfo *>())
|
2011-11-01 09:16:03 +08:00
|
|
|
return TSInfo->getTypeLoc().getLocalSourceRange().getBegin();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2018-04-03 08:11:50 +08:00
|
|
|
return {};
|
2009-12-03 06:36:29 +08:00
|
|
|
}
|
|
|
|
|
2011-01-09 04:30:50 +08:00
|
|
|
SourceRange CXXCtorInitializer::getSourceRange() const {
|
2011-06-12 01:19:42 +08:00
|
|
|
if (isInClassMemberInitializer()) {
|
|
|
|
FieldDecl *D = getAnyMember();
|
|
|
|
if (Expr *I = D->getInClassInitializer())
|
|
|
|
return I->getSourceRange();
|
2018-04-03 08:11:50 +08:00
|
|
|
return {};
|
2011-06-12 01:19:42 +08:00
|
|
|
}
|
|
|
|
|
2009-12-03 06:36:29 +08:00
|
|
|
return SourceRange(getSourceLocation(), getRParenLoc());
|
2008-11-05 12:29:56 +08:00
|
|
|
}
|
|
|
|
|
2018-08-02 05:02:40 +08:00
|
|
|
CXXConstructorDecl::CXXConstructorDecl(
|
|
|
|
ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
|
|
|
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
2019-05-09 11:59:21 +08:00
|
|
|
ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared,
|
2020-01-09 21:07:51 +08:00
|
|
|
ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited,
|
|
|
|
Expr *TrailingRequiresClause)
|
2018-08-02 05:02:40 +08:00
|
|
|
: CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo,
|
2020-01-09 21:07:51 +08:00
|
|
|
SC_None, isInline, ConstexprKind, SourceLocation(),
|
|
|
|
TrailingRequiresClause) {
|
2018-08-02 05:02:40 +08:00
|
|
|
setNumCtorInitializers(0);
|
|
|
|
setInheritingConstructor(static_cast<bool>(Inherited));
|
|
|
|
setImplicit(isImplicitlyDeclared);
|
2019-05-09 11:59:21 +08:00
|
|
|
CXXConstructorDeclBits.HasTrailingExplicitSpecifier = ES.getExpr() ? 1 : 0;
|
2018-08-02 05:02:40 +08:00
|
|
|
if (Inherited)
|
|
|
|
*getTrailingObjects<InheritedConstructor>() = Inherited;
|
2019-05-09 11:59:21 +08:00
|
|
|
setExplicitSpecifier(ES);
|
2018-08-02 05:02:40 +08:00
|
|
|
}
|
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void CXXConstructorDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID,
|
2019-05-09 11:59:21 +08:00
|
|
|
uint64_t AllocKind) {
|
|
|
|
bool hasTraillingExplicit = static_cast<bool>(AllocKind & TAKHasTailExplicit);
|
|
|
|
bool isInheritingConstructor =
|
|
|
|
static_cast<bool>(AllocKind & TAKInheritsConstructor);
|
|
|
|
unsigned Extra =
|
|
|
|
additionalSizeToAlloc<InheritedConstructor, ExplicitSpecifier>(
|
|
|
|
isInheritingConstructor, hasTraillingExplicit);
|
2019-06-14 16:56:20 +08:00
|
|
|
auto *Result = new (C, ID, Extra)
|
|
|
|
CXXConstructorDecl(C, nullptr, SourceLocation(), DeclarationNameInfo(),
|
|
|
|
QualType(), nullptr, ExplicitSpecifier(), false, false,
|
2020-01-09 21:07:51 +08:00
|
|
|
CSK_unspecified, InheritedConstructor(), nullptr);
|
2019-05-09 11:59:21 +08:00
|
|
|
Result->setInheritingConstructor(isInheritingConstructor);
|
|
|
|
Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier =
|
|
|
|
hasTraillingExplicit;
|
|
|
|
Result->setExplicitSpecifier(ExplicitSpecifier());
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
return Result;
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2019-05-09 11:59:21 +08:00
|
|
|
CXXConstructorDecl *CXXConstructorDecl::Create(
|
|
|
|
ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
|
|
|
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
|
|
|
ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared,
|
2020-01-09 21:07:51 +08:00
|
|
|
ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited,
|
|
|
|
Expr *TrailingRequiresClause) {
|
2010-08-12 06:01:17 +08:00
|
|
|
assert(NameInfo.getName().getNameKind()
|
|
|
|
== DeclarationName::CXXConstructorName &&
|
2008-11-17 22:58:09 +08:00
|
|
|
"Name must refer to a constructor");
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
unsigned Extra =
|
2019-05-09 11:59:21 +08:00
|
|
|
additionalSizeToAlloc<InheritedConstructor, ExplicitSpecifier>(
|
|
|
|
Inherited ? 1 : 0, ES.getExpr() ? 1 : 0);
|
|
|
|
return new (C, RD, Extra)
|
|
|
|
CXXConstructorDecl(C, RD, StartLoc, NameInfo, T, TInfo, ES, isInline,
|
2020-01-09 21:07:51 +08:00
|
|
|
isImplicitlyDeclared, ConstexprKind, Inherited,
|
|
|
|
TrailingRequiresClause);
|
2008-10-31 17:07:45 +08:00
|
|
|
}
|
|
|
|
|
2015-03-24 14:36:48 +08:00
|
|
|
CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const {
|
|
|
|
return CtorInitializers.get(getASTContext().getExternalSource());
|
|
|
|
}
|
|
|
|
|
2011-11-01 09:16:03 +08:00
|
|
|
CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const {
|
|
|
|
assert(isDelegatingConstructor() && "Not a delegating constructor!");
|
|
|
|
Expr *E = (*init_begin())->getInit()->IgnoreImplicit();
|
2018-04-03 08:11:50 +08:00
|
|
|
if (const auto *Construct = dyn_cast<CXXConstructExpr>(E))
|
2011-11-01 09:16:03 +08:00
|
|
|
return Construct->getConstructor();
|
2014-05-12 13:36:57 +08:00
|
|
|
|
|
|
|
return nullptr;
|
2011-11-01 09:16:03 +08:00
|
|
|
}
|
|
|
|
|
2008-11-01 04:25:05 +08:00
|
|
|
bool CXXConstructorDecl::isDefaultConstructor() const {
|
2020-06-03 01:42:36 +08:00
|
|
|
// C++ [class.default.ctor]p1:
|
|
|
|
// A default constructor for a class X is a constructor of class X for
|
|
|
|
// which each parameter that is not a function parameter pack has a default
|
|
|
|
// argument (including the case of a constructor with no parameters)
|
|
|
|
return getMinRequiredArguments() == 0;
|
2008-11-01 04:25:05 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
bool
|
2009-12-22 08:34:07 +08:00
|
|
|
CXXConstructorDecl::isCopyConstructor(unsigned &TypeQuals) const {
|
2011-01-22 03:38:21 +08:00
|
|
|
return isCopyOrMoveConstructor(TypeQuals) &&
|
|
|
|
getParamDecl(0)->getType()->isLValueReferenceType();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CXXConstructorDecl::isMoveConstructor(unsigned &TypeQuals) const {
|
|
|
|
return isCopyOrMoveConstructor(TypeQuals) &&
|
2020-06-03 01:42:36 +08:00
|
|
|
getParamDecl(0)->getType()->isRValueReferenceType();
|
2011-01-22 03:38:21 +08:00
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Determine whether this is a copy or move constructor.
|
2011-01-22 03:38:21 +08:00
|
|
|
bool CXXConstructorDecl::isCopyOrMoveConstructor(unsigned &TypeQuals) const {
|
2008-11-01 04:25:05 +08:00
|
|
|
// C++ [class.copy]p2:
|
2008-11-06 00:20:31 +08:00
|
|
|
// A non-template constructor for class X is a copy constructor
|
|
|
|
// if its first parameter is of type X&, const X&, volatile X& or
|
|
|
|
// const volatile X&, and either there are no other parameters
|
|
|
|
// or else all other parameters have default arguments (8.3.6).
|
2011-01-22 03:38:21 +08:00
|
|
|
// C++0x [class.copy]p3:
|
|
|
|
// A non-template constructor for class X is a move constructor if its
|
2018-07-31 03:24:48 +08:00
|
|
|
// first parameter is of type X&&, const X&&, volatile X&&, or
|
|
|
|
// const volatile X&&, and either there are no other parameters or else
|
2011-01-22 03:38:21 +08:00
|
|
|
// all other parameters have default arguments.
|
2020-06-03 01:42:36 +08:00
|
|
|
if (!hasOneParamOrDefaultArgs() || getPrimaryTemplate() != nullptr ||
|
|
|
|
getDescribedFunctionTemplate() != nullptr)
|
2008-11-01 04:25:05 +08:00
|
|
|
return false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2008-11-01 04:25:05 +08:00
|
|
|
const ParmVarDecl *Param = getParamDecl(0);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
|
|
|
// Do we have a reference type?
|
2018-04-03 08:11:50 +08:00
|
|
|
const auto *ParamRefType = Param->getType()->getAs<ReferenceType>();
|
2009-11-14 07:59:09 +08:00
|
|
|
if (!ParamRefType)
|
|
|
|
return false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-11-14 07:59:09 +08:00
|
|
|
// Is it a reference to our class type?
|
2009-12-22 08:34:07 +08:00
|
|
|
ASTContext &Context = getASTContext();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-11-14 07:59:09 +08:00
|
|
|
CanQualType PointeeType
|
|
|
|
= Context.getCanonicalType(ParamRefType->getPointeeType());
|
2018-07-31 03:24:48 +08:00
|
|
|
CanQualType ClassTy
|
2009-09-16 04:50:23 +08:00
|
|
|
= Context.getCanonicalType(Context.getTagDeclType(getParent()));
|
2008-11-01 04:25:05 +08:00
|
|
|
if (PointeeType.getUnqualifiedType() != ClassTy)
|
|
|
|
return false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-09-25 03:53:00 +08:00
|
|
|
// FIXME: other qualifiers?
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-01-22 03:38:21 +08:00
|
|
|
// We have a copy or move constructor.
|
2008-11-01 04:25:05 +08:00
|
|
|
TypeQuals = PointeeType.getCVRQualifiers();
|
2018-07-31 03:24:48 +08:00
|
|
|
return true;
|
2008-11-01 04:25:05 +08:00
|
|
|
}
|
|
|
|
|
2009-08-29 00:57:08 +08:00
|
|
|
bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const {
|
2008-11-01 00:23:19 +08:00
|
|
|
// C++ [class.conv.ctor]p1:
|
|
|
|
// A constructor declared without the function-specifier explicit
|
|
|
|
// that can be called with a single parameter specifies a
|
|
|
|
// conversion from the type of its first parameter to the type of
|
|
|
|
// its class. Such a constructor is called a converting
|
|
|
|
// constructor.
|
2009-08-29 00:57:08 +08:00
|
|
|
if (isExplicit() && !AllowExplicit)
|
2008-11-01 00:23:19 +08:00
|
|
|
return false;
|
|
|
|
|
2020-06-03 01:42:36 +08:00
|
|
|
// FIXME: This has nothing to do with the definition of converting
|
|
|
|
// constructor, but is convenient for how we use this function in overload
|
|
|
|
// resolution.
|
|
|
|
return getNumParams() == 0
|
|
|
|
? getType()->castAs<FunctionProtoType>()->isVariadic()
|
|
|
|
: getMinRequiredArguments() <= 1;
|
2008-11-01 00:23:19 +08:00
|
|
|
}
|
2008-10-31 17:07:45 +08:00
|
|
|
|
2010-11-09 01:16:59 +08:00
|
|
|
bool CXXConstructorDecl::isSpecializationCopyingObject() const {
|
2020-06-03 01:42:36 +08:00
|
|
|
if (!hasOneParamOrDefaultArgs() || getDescribedFunctionTemplate() != nullptr)
|
2009-11-14 09:20:54 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
const ParmVarDecl *Param = getParamDecl(0);
|
|
|
|
|
|
|
|
ASTContext &Context = getASTContext();
|
|
|
|
CanQualType ParamType = Context.getCanonicalType(Param->getType());
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2018-04-06 23:14:32 +08:00
|
|
|
// Is it the same as our class type?
|
2018-07-31 03:24:48 +08:00
|
|
|
CanQualType ClassTy
|
2009-11-14 09:20:54 +08:00
|
|
|
= Context.getCanonicalType(Context.getTagDeclType(getParent()));
|
|
|
|
if (ParamType.getUnqualifiedType() != ClassTy)
|
|
|
|
return false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
|
|
|
return true;
|
2009-11-14 09:20:54 +08:00
|
|
|
}
|
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void CXXDestructorDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
2010-05-08 05:43:38 +08:00
|
|
|
CXXDestructorDecl *
|
2012-01-06 05:55:30 +08:00
|
|
|
CXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
return new (C, ID)
|
|
|
|
CXXDestructorDecl(C, nullptr, SourceLocation(), DeclarationNameInfo(),
|
2020-01-09 21:07:51 +08:00
|
|
|
QualType(), nullptr, false, false, CSK_unspecified,
|
|
|
|
nullptr);
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2019-09-23 11:48:44 +08:00
|
|
|
CXXDestructorDecl *CXXDestructorDecl::Create(
|
|
|
|
ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
|
|
|
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
2020-01-09 21:07:51 +08:00
|
|
|
bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
|
|
|
|
Expr *TrailingRequiresClause) {
|
2010-08-12 06:01:17 +08:00
|
|
|
assert(NameInfo.getName().getNameKind()
|
|
|
|
== DeclarationName::CXXDestructorName &&
|
2008-11-17 22:58:09 +08:00
|
|
|
"Name must refer to a destructor");
|
2019-09-23 11:48:44 +08:00
|
|
|
return new (C, RD)
|
|
|
|
CXXDestructorDecl(C, RD, StartLoc, NameInfo, T, TInfo, isInline,
|
2020-01-09 21:07:51 +08:00
|
|
|
isImplicitlyDeclared, ConstexprKind,
|
|
|
|
TrailingRequiresClause);
|
2008-11-06 04:51:48 +08:00
|
|
|
}
|
|
|
|
|
2017-10-13 09:55:36 +08:00
|
|
|
void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) {
|
2015-03-10 09:41:22 +08:00
|
|
|
auto *First = cast<CXXDestructorDecl>(getFirstDecl());
|
|
|
|
if (OD && !First->OperatorDelete) {
|
|
|
|
First->OperatorDelete = OD;
|
2017-10-13 09:55:36 +08:00
|
|
|
First->OperatorDeleteThisArg = ThisArg;
|
2015-03-10 09:41:22 +08:00
|
|
|
if (auto *L = getASTMutationListener())
|
2017-10-13 09:55:36 +08:00
|
|
|
L->ResolvedOperatorDelete(First, OD, ThisArg);
|
2015-03-10 09:41:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void CXXConversionDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
2010-05-08 05:43:38 +08:00
|
|
|
CXXConversionDecl *
|
2012-01-06 05:55:30 +08:00
|
|
|
CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2019-05-09 11:59:21 +08:00
|
|
|
return new (C, ID) CXXConversionDecl(
|
|
|
|
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
|
2020-01-09 21:07:51 +08:00
|
|
|
false, ExplicitSpecifier(), CSK_unspecified, SourceLocation(), nullptr);
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2019-05-09 11:59:21 +08:00
|
|
|
CXXConversionDecl *CXXConversionDecl::Create(
|
|
|
|
ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
|
|
|
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
2019-06-14 16:56:20 +08:00
|
|
|
bool isInline, ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind,
|
2020-01-09 21:07:51 +08:00
|
|
|
SourceLocation EndLocation, Expr *TrailingRequiresClause) {
|
2010-08-12 06:01:17 +08:00
|
|
|
assert(NameInfo.getName().getNameKind()
|
|
|
|
== DeclarationName::CXXConversionFunctionName &&
|
2008-11-17 22:58:09 +08:00
|
|
|
"Name must refer to a conversion function");
|
2019-06-14 16:56:20 +08:00
|
|
|
return new (C, RD)
|
|
|
|
CXXConversionDecl(C, RD, StartLoc, NameInfo, T, TInfo, isInline, ES,
|
2020-01-09 21:07:51 +08:00
|
|
|
ConstexprKind, EndLocation, TrailingRequiresClause);
|
2008-11-08 04:08:42 +08:00
|
|
|
}
|
|
|
|
|
2012-02-16 09:06:16 +08:00
|
|
|
bool CXXConversionDecl::isLambdaToBlockPointerConversion() const {
|
|
|
|
return isImplicit() && getParent()->isLambda() &&
|
|
|
|
getConversionType()->isBlockPointerType();
|
|
|
|
}
|
|
|
|
|
2018-08-02 05:16:54 +08:00
|
|
|
LinkageSpecDecl::LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc,
|
|
|
|
SourceLocation LangLoc, LanguageIDs lang,
|
|
|
|
bool HasBraces)
|
|
|
|
: Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec),
|
|
|
|
ExternLoc(ExternLoc), RBraceLoc(SourceLocation()) {
|
|
|
|
setLanguage(lang);
|
|
|
|
LinkageSpecDeclBits.HasBraces = HasBraces;
|
|
|
|
}
|
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void LinkageSpecDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
2008-11-05 00:51:42 +08:00
|
|
|
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
|
2009-09-09 23:08:12 +08:00
|
|
|
DeclContext *DC,
|
2011-03-09 00:41:52 +08:00
|
|
|
SourceLocation ExternLoc,
|
|
|
|
SourceLocation LangLoc,
|
2011-03-03 22:52:38 +08:00
|
|
|
LanguageIDs Lang,
|
2013-04-26 09:30:23 +08:00
|
|
|
bool HasBraces) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, DC) LinkageSpecDecl(DC, ExternLoc, LangLoc, Lang, HasBraces);
|
2008-12-17 06:23:02 +08:00
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
2013-11-22 17:01:48 +08:00
|
|
|
LinkageSpecDecl *LinkageSpecDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
2014-05-12 13:36:57 +08:00
|
|
|
return new (C, ID) LinkageSpecDecl(nullptr, SourceLocation(),
|
|
|
|
SourceLocation(), lang_c, false);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void UsingDirectiveDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation L,
|
|
|
|
SourceLocation NamespaceLoc,
|
2011-02-26 00:33:46 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc,
|
2009-02-04 03:21:40 +08:00
|
|
|
SourceLocation IdentLoc,
|
2009-11-23 23:34:23 +08:00
|
|
|
NamedDecl *Used,
|
2009-02-04 03:21:40 +08:00
|
|
|
DeclContext *CommonAncestor) {
|
2018-04-03 08:11:50 +08:00
|
|
|
if (auto *NS = dyn_cast_or_null<NamespaceDecl>(Used))
|
2009-11-23 23:34:23 +08:00
|
|
|
Used = NS->getOriginalNamespace();
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, DC) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierLoc,
|
|
|
|
IdentLoc, Used, CommonAncestor);
|
2009-02-04 03:21:40 +08:00
|
|
|
}
|
|
|
|
|
2013-11-22 17:01:48 +08:00
|
|
|
UsingDirectiveDecl *UsingDirectiveDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
2014-05-12 13:36:57 +08:00
|
|
|
return new (C, ID) UsingDirectiveDecl(nullptr, SourceLocation(),
|
|
|
|
SourceLocation(),
|
2013-11-22 17:01:48 +08:00
|
|
|
NestedNameSpecifierLoc(),
|
2014-05-12 13:36:57 +08:00
|
|
|
SourceLocation(), nullptr, nullptr);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2009-11-23 23:34:23 +08:00
|
|
|
NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() {
|
2018-04-03 08:11:50 +08:00
|
|
|
if (auto *NA = dyn_cast_or_null<NamespaceAliasDecl>(NominatedNamespace))
|
2009-11-23 23:34:23 +08:00
|
|
|
return NA->getNamespace();
|
|
|
|
return cast_or_null<NamespaceDecl>(NominatedNamespace);
|
|
|
|
}
|
|
|
|
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
NamespaceDecl::NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
|
|
|
|
SourceLocation StartLoc, SourceLocation IdLoc,
|
|
|
|
IdentifierInfo *Id, NamespaceDecl *PrevDecl)
|
|
|
|
: NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace),
|
2017-11-15 07:13:32 +08:00
|
|
|
redeclarable_base(C), LocStart(StartLoc),
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
AnonOrFirstNamespaceAndInline(nullptr, Inline) {
|
2013-10-17 23:37:26 +08:00
|
|
|
setPreviousDecl(PrevDecl);
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
|
2012-01-07 17:11:48 +08:00
|
|
|
if (PrevDecl)
|
|
|
|
AnonOrFirstNamespaceAndInline.setPointer(PrevDecl->getOriginalNamespace());
|
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
|
2012-01-07 17:11:48 +08:00
|
|
|
bool Inline, SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc, IdentifierInfo *Id,
|
|
|
|
NamespaceDecl *PrevDecl) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
return new (C, DC) NamespaceDecl(C, DC, Inline, StartLoc, IdLoc, Id,
|
|
|
|
PrevDecl);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
NamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
return new (C, ID) NamespaceDecl(C, nullptr, false, SourceLocation(),
|
2014-05-12 13:36:57 +08:00
|
|
|
SourceLocation(), nullptr, nullptr);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2015-12-30 11:24:14 +08:00
|
|
|
NamespaceDecl *NamespaceDecl::getOriginalNamespace() {
|
|
|
|
if (isFirstDecl())
|
|
|
|
return this;
|
|
|
|
|
|
|
|
return AnonOrFirstNamespaceAndInline.getPointer();
|
|
|
|
}
|
|
|
|
|
|
|
|
const NamespaceDecl *NamespaceDecl::getOriginalNamespace() const {
|
|
|
|
if (isFirstDecl())
|
|
|
|
return this;
|
|
|
|
|
|
|
|
return AnonOrFirstNamespaceAndInline.getPointer();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NamespaceDecl::isOriginalNamespace() const { return isFirstDecl(); }
|
|
|
|
|
2014-05-10 09:17:36 +08:00
|
|
|
NamespaceDecl *NamespaceDecl::getNextRedeclarationImpl() {
|
|
|
|
return getNextRedeclaration();
|
2013-11-26 23:12:20 +08:00
|
|
|
}
|
2017-11-15 07:13:32 +08:00
|
|
|
|
2013-11-26 23:12:20 +08:00
|
|
|
NamespaceDecl *NamespaceDecl::getPreviousDeclImpl() {
|
|
|
|
return getPreviousDecl();
|
|
|
|
}
|
2017-11-15 07:13:32 +08:00
|
|
|
|
2013-11-26 23:12:20 +08:00
|
|
|
NamespaceDecl *NamespaceDecl::getMostRecentDeclImpl() {
|
|
|
|
return getMostRecentDecl();
|
|
|
|
}
|
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void NamespaceAliasDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
2014-09-04 07:11:22 +08:00
|
|
|
NamespaceAliasDecl *NamespaceAliasDecl::getNextRedeclarationImpl() {
|
|
|
|
return getNextRedeclaration();
|
|
|
|
}
|
2017-11-15 07:13:32 +08:00
|
|
|
|
2014-09-04 07:11:22 +08:00
|
|
|
NamespaceAliasDecl *NamespaceAliasDecl::getPreviousDeclImpl() {
|
|
|
|
return getPreviousDecl();
|
|
|
|
}
|
2017-11-15 07:13:32 +08:00
|
|
|
|
2014-09-04 07:11:22 +08:00
|
|
|
NamespaceAliasDecl *NamespaceAliasDecl::getMostRecentDeclImpl() {
|
|
|
|
return getMostRecentDecl();
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
|
2010-09-01 11:07:18 +08:00
|
|
|
SourceLocation UsingLoc,
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation AliasLoc,
|
|
|
|
IdentifierInfo *Alias,
|
2011-02-26 01:08:07 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc,
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation IdentLoc,
|
2009-03-29 06:58:02 +08:00
|
|
|
NamedDecl *Namespace) {
|
2014-09-04 07:11:22 +08:00
|
|
|
// FIXME: Preserve the aliased namespace as written.
|
2018-04-03 08:11:50 +08:00
|
|
|
if (auto *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
|
2009-11-23 23:34:23 +08:00
|
|
|
Namespace = NS->getOriginalNamespace();
|
2014-09-04 07:11:22 +08:00
|
|
|
return new (C, DC) NamespaceAliasDecl(C, DC, UsingLoc, AliasLoc, Alias,
|
2013-11-22 17:01:48 +08:00
|
|
|
QualifierLoc, IdentLoc, Namespace);
|
2009-03-29 06:58:02 +08:00
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
NamespaceAliasDecl *
|
|
|
|
NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2014-09-04 07:11:22 +08:00
|
|
|
return new (C, ID) NamespaceAliasDecl(C, nullptr, SourceLocation(),
|
2014-05-12 13:36:57 +08:00
|
|
|
SourceLocation(), nullptr,
|
|
|
|
NestedNameSpecifierLoc(),
|
|
|
|
SourceLocation(), nullptr);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2019-11-17 18:41:55 +08:00
|
|
|
void LifetimeExtendedTemporaryDecl::anchor() {}
|
|
|
|
|
|
|
|
/// Retrieve the storage duration for the materialized temporary.
|
|
|
|
StorageDuration LifetimeExtendedTemporaryDecl::getStorageDuration() const {
|
|
|
|
const ValueDecl *ExtendingDecl = getExtendingDecl();
|
|
|
|
if (!ExtendingDecl)
|
|
|
|
return SD_FullExpression;
|
|
|
|
// FIXME: This is not necessarily correct for a temporary materialized
|
|
|
|
// within a default initializer.
|
|
|
|
if (isa<FieldDecl>(ExtendingDecl))
|
|
|
|
return SD_Automatic;
|
|
|
|
// FIXME: This only works because storage class specifiers are not allowed
|
|
|
|
// on decomposition declarations.
|
|
|
|
if (isa<BindingDecl>(ExtendingDecl))
|
|
|
|
return ExtendingDecl->getDeclContext()->isFunctionOrMethod() ? SD_Automatic
|
|
|
|
: SD_Static;
|
|
|
|
return cast<VarDecl>(ExtendingDecl)->getStorageDuration();
|
|
|
|
}
|
|
|
|
|
|
|
|
APValue *LifetimeExtendedTemporaryDecl::getOrCreateValue(bool MayCreate) const {
|
|
|
|
assert(getStorageDuration() == SD_Static &&
|
|
|
|
"don't need to cache the computed value for this temporary");
|
2019-11-20 04:05:30 +08:00
|
|
|
if (MayCreate && !Value) {
|
2019-11-17 18:41:55 +08:00
|
|
|
Value = (new (getASTContext()) APValue);
|
2019-11-20 04:05:30 +08:00
|
|
|
getASTContext().addDestruction(Value);
|
|
|
|
}
|
2019-11-17 18:41:55 +08:00
|
|
|
assert(Value && "may not be null");
|
|
|
|
return Value;
|
|
|
|
}
|
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void UsingShadowDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation Loc, UsingDecl *Using,
|
|
|
|
NamedDecl *Target)
|
|
|
|
: NamedDecl(K, DC, Loc, Using ? Using->getDeclName() : DeclarationName()),
|
2018-04-03 08:11:50 +08:00
|
|
|
redeclarable_base(C), UsingOrNextShadow(cast<NamedDecl>(Using)) {
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
if (Target)
|
2018-01-06 09:07:05 +08:00
|
|
|
setTargetDecl(Target);
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
setImplicit();
|
|
|
|
}
|
|
|
|
|
|
|
|
UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, EmptyShell Empty)
|
|
|
|
: NamedDecl(K, nullptr, SourceLocation(), DeclarationName()),
|
2017-11-15 07:13:32 +08:00
|
|
|
redeclarable_base(C) {}
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
UsingShadowDecl *
|
|
|
|
UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
return new (C, ID) UsingShadowDecl(UsingShadow, C, EmptyShell());
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2010-11-10 13:40:41 +08:00
|
|
|
UsingDecl *UsingShadowDecl::getUsingDecl() const {
|
|
|
|
const UsingShadowDecl *Shadow = this;
|
2018-04-03 08:11:50 +08:00
|
|
|
while (const auto *NextShadow =
|
|
|
|
dyn_cast<UsingShadowDecl>(Shadow->UsingOrNextShadow))
|
2010-11-10 13:40:41 +08:00
|
|
|
Shadow = NextShadow;
|
|
|
|
return cast<UsingDecl>(Shadow->UsingOrNextShadow);
|
|
|
|
}
|
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void ConstructorUsingShadowDecl::anchor() {}
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
|
|
|
|
ConstructorUsingShadowDecl *
|
|
|
|
ConstructorUsingShadowDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation Loc, UsingDecl *Using,
|
|
|
|
NamedDecl *Target, bool IsVirtual) {
|
|
|
|
return new (C, DC) ConstructorUsingShadowDecl(C, DC, Loc, Using, Target,
|
|
|
|
IsVirtual);
|
|
|
|
}
|
|
|
|
|
|
|
|
ConstructorUsingShadowDecl *
|
|
|
|
ConstructorUsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
|
|
|
return new (C, ID) ConstructorUsingShadowDecl(C, EmptyShell());
|
|
|
|
}
|
|
|
|
|
|
|
|
CXXRecordDecl *ConstructorUsingShadowDecl::getNominatedBaseClass() const {
|
|
|
|
return getUsingDecl()->getQualifier()->getAsRecordDecl();
|
|
|
|
}
|
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void UsingDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
2010-11-10 13:40:41 +08:00
|
|
|
void UsingDecl::addShadowDecl(UsingShadowDecl *S) {
|
|
|
|
assert(std::find(shadow_begin(), shadow_end(), S) == shadow_end() &&
|
|
|
|
"declaration already in set");
|
|
|
|
assert(S->getUsingDecl() == this);
|
|
|
|
|
2012-01-08 03:09:05 +08:00
|
|
|
if (FirstUsingShadow.getPointer())
|
|
|
|
S->UsingOrNextShadow = FirstUsingShadow.getPointer();
|
|
|
|
FirstUsingShadow.setPointer(S);
|
2010-11-10 13:40:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void UsingDecl::removeShadowDecl(UsingShadowDecl *S) {
|
|
|
|
assert(std::find(shadow_begin(), shadow_end(), S) != shadow_end() &&
|
|
|
|
"declaration not in set");
|
|
|
|
assert(S->getUsingDecl() == this);
|
|
|
|
|
|
|
|
// Remove S from the shadow decl chain. This is O(n) but hopefully rare.
|
|
|
|
|
2012-01-08 03:09:05 +08:00
|
|
|
if (FirstUsingShadow.getPointer() == S) {
|
|
|
|
FirstUsingShadow.setPointer(
|
|
|
|
dyn_cast<UsingShadowDecl>(S->UsingOrNextShadow));
|
2010-11-10 13:40:41 +08:00
|
|
|
S->UsingOrNextShadow = this;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-01-08 03:09:05 +08:00
|
|
|
UsingShadowDecl *Prev = FirstUsingShadow.getPointer();
|
2010-11-10 13:40:41 +08:00
|
|
|
while (Prev->UsingOrNextShadow != S)
|
|
|
|
Prev = cast<UsingShadowDecl>(Prev->UsingOrNextShadow);
|
|
|
|
Prev->UsingOrNextShadow = S->UsingOrNextShadow;
|
|
|
|
S->UsingOrNextShadow = this;
|
|
|
|
}
|
|
|
|
|
2011-02-25 08:36:19 +08:00
|
|
|
UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL,
|
|
|
|
NestedNameSpecifierLoc QualifierLoc,
|
2010-08-12 19:46:03 +08:00
|
|
|
const DeclarationNameInfo &NameInfo,
|
2013-07-22 18:54:09 +08:00
|
|
|
bool HasTypename) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, DC) UsingDecl(DC, UL, QualifierLoc, NameInfo, HasTypename);
|
2009-06-20 08:51:54 +08:00
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
UsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2014-05-12 13:36:57 +08:00
|
|
|
return new (C, ID) UsingDecl(nullptr, SourceLocation(),
|
|
|
|
NestedNameSpecifierLoc(), DeclarationNameInfo(),
|
|
|
|
false);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2013-07-18 01:28:56 +08:00
|
|
|
SourceRange UsingDecl::getSourceRange() const {
|
|
|
|
SourceLocation Begin = isAccessDeclaration()
|
|
|
|
? getQualifierLoc().getBeginLoc() : UsingLocation;
|
|
|
|
return SourceRange(Begin, getNameInfo().getEndLoc());
|
|
|
|
}
|
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void UsingPackDecl::anchor() {}
|
2016-12-21 05:35:28 +08:00
|
|
|
|
|
|
|
UsingPackDecl *UsingPackDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
NamedDecl *InstantiatedFrom,
|
|
|
|
ArrayRef<NamedDecl *> UsingDecls) {
|
|
|
|
size_t Extra = additionalSizeToAlloc<NamedDecl *>(UsingDecls.size());
|
|
|
|
return new (C, DC, Extra) UsingPackDecl(DC, InstantiatedFrom, UsingDecls);
|
|
|
|
}
|
|
|
|
|
|
|
|
UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, unsigned ID,
|
|
|
|
unsigned NumExpansions) {
|
|
|
|
size_t Extra = additionalSizeToAlloc<NamedDecl *>(NumExpansions);
|
|
|
|
auto *Result = new (C, ID, Extra) UsingPackDecl(nullptr, nullptr, None);
|
|
|
|
Result->NumExpansions = NumExpansions;
|
|
|
|
auto *Trail = Result->getTrailingObjects<NamedDecl *>();
|
|
|
|
for (unsigned I = 0; I != NumExpansions; ++I)
|
|
|
|
new (Trail + I) NamedDecl*(nullptr);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void UnresolvedUsingValueDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
2009-11-18 10:36:19 +08:00
|
|
|
UnresolvedUsingValueDecl *
|
|
|
|
UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation UsingLoc,
|
2011-02-25 08:36:19 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc,
|
2016-12-21 05:35:28 +08:00
|
|
|
const DeclarationNameInfo &NameInfo,
|
|
|
|
SourceLocation EllipsisLoc) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, DC) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc,
|
2016-12-21 05:35:28 +08:00
|
|
|
QualifierLoc, NameInfo,
|
|
|
|
EllipsisLoc);
|
2009-11-18 10:36:19 +08:00
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
UnresolvedUsingValueDecl *
|
|
|
|
UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2014-05-12 13:36:57 +08:00
|
|
|
return new (C, ID) UnresolvedUsingValueDecl(nullptr, QualType(),
|
|
|
|
SourceLocation(),
|
2013-11-22 17:01:48 +08:00
|
|
|
NestedNameSpecifierLoc(),
|
2016-12-21 05:35:28 +08:00
|
|
|
DeclarationNameInfo(),
|
|
|
|
SourceLocation());
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2013-07-18 01:28:56 +08:00
|
|
|
SourceRange UnresolvedUsingValueDecl::getSourceRange() const {
|
|
|
|
SourceLocation Begin = isAccessDeclaration()
|
|
|
|
? getQualifierLoc().getBeginLoc() : UsingLocation;
|
|
|
|
return SourceRange(Begin, getNameInfo().getEndLoc());
|
|
|
|
}
|
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void UnresolvedUsingTypenameDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
2009-11-18 10:36:19 +08:00
|
|
|
UnresolvedUsingTypenameDecl *
|
|
|
|
UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation UsingLoc,
|
|
|
|
SourceLocation TypenameLoc,
|
2011-02-25 08:36:19 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc,
|
2009-11-18 10:36:19 +08:00
|
|
|
SourceLocation TargetNameLoc,
|
2016-12-21 05:35:28 +08:00
|
|
|
DeclarationName TargetName,
|
|
|
|
SourceLocation EllipsisLoc) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, DC) UnresolvedUsingTypenameDecl(
|
|
|
|
DC, UsingLoc, TypenameLoc, QualifierLoc, TargetNameLoc,
|
2016-12-21 05:35:28 +08:00
|
|
|
TargetName.getAsIdentifierInfo(), EllipsisLoc);
|
2009-08-28 13:30:28 +08:00
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
UnresolvedUsingTypenameDecl *
|
|
|
|
UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, ID) UnresolvedUsingTypenameDecl(
|
2014-05-12 13:36:57 +08:00
|
|
|
nullptr, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(),
|
2016-12-21 05:35:28 +08:00
|
|
|
SourceLocation(), nullptr, SourceLocation());
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2017-11-15 07:13:32 +08:00
|
|
|
void StaticAssertDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
2009-03-14 08:25:26 +08:00
|
|
|
StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
|
2011-03-09 00:41:52 +08:00
|
|
|
SourceLocation StaticAssertLoc,
|
|
|
|
Expr *AssertExpr,
|
|
|
|
StringLiteral *Message,
|
2012-07-12 06:37:56 +08:00
|
|
|
SourceLocation RParenLoc,
|
|
|
|
bool Failed) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, DC) StaticAssertDecl(DC, StaticAssertLoc, AssertExpr, Message,
|
|
|
|
RParenLoc, Failed);
|
2009-03-14 08:25:26 +08:00
|
|
|
}
|
|
|
|
|
2013-11-22 17:01:48 +08:00
|
|
|
StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C,
|
2012-01-06 05:55:30 +08:00
|
|
|
unsigned ID) {
|
2014-05-12 13:36:57 +08:00
|
|
|
return new (C, ID) StaticAssertDecl(nullptr, SourceLocation(), nullptr,
|
|
|
|
nullptr, SourceLocation(), false);
|
2013-11-22 17:01:48 +08:00
|
|
|
}
|
|
|
|
|
2016-07-23 07:36:59 +08:00
|
|
|
void BindingDecl::anchor() {}
|
|
|
|
|
|
|
|
BindingDecl *BindingDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation IdLoc, IdentifierInfo *Id) {
|
2016-08-12 08:53:41 +08:00
|
|
|
return new (C, DC) BindingDecl(DC, IdLoc, Id);
|
2016-07-23 07:36:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
BindingDecl *BindingDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2016-08-12 08:53:41 +08:00
|
|
|
return new (C, ID) BindingDecl(nullptr, SourceLocation(), nullptr);
|
2016-07-23 07:36:59 +08:00
|
|
|
}
|
|
|
|
|
2019-05-25 09:04:17 +08:00
|
|
|
ValueDecl *BindingDecl::getDecomposedDecl() const {
|
|
|
|
ExternalASTSource *Source =
|
|
|
|
Decomp.isOffset() ? getASTContext().getExternalSource() : nullptr;
|
|
|
|
return cast_or_null<ValueDecl>(Decomp.get(Source));
|
|
|
|
}
|
|
|
|
|
2016-08-15 07:15:52 +08:00
|
|
|
VarDecl *BindingDecl::getHoldingVar() const {
|
|
|
|
Expr *B = getBinding();
|
|
|
|
if (!B)
|
|
|
|
return nullptr;
|
|
|
|
auto *DRE = dyn_cast<DeclRefExpr>(B->IgnoreImplicit());
|
|
|
|
if (!DRE)
|
|
|
|
return nullptr;
|
|
|
|
|
2020-03-12 22:32:33 +08:00
|
|
|
auto *VD = cast<VarDecl>(DRE->getDecl());
|
2016-08-15 07:15:52 +08:00
|
|
|
assert(VD->isImplicit() && "holding var for binding decl not implicit");
|
|
|
|
return VD;
|
|
|
|
}
|
|
|
|
|
2016-07-23 07:36:59 +08:00
|
|
|
void DecompositionDecl::anchor() {}
|
|
|
|
|
|
|
|
DecompositionDecl *DecompositionDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation StartLoc,
|
|
|
|
SourceLocation LSquareLoc,
|
|
|
|
QualType T, TypeSourceInfo *TInfo,
|
|
|
|
StorageClass SC,
|
|
|
|
ArrayRef<BindingDecl *> Bindings) {
|
|
|
|
size_t Extra = additionalSizeToAlloc<BindingDecl *>(Bindings.size());
|
|
|
|
return new (C, DC, Extra)
|
|
|
|
DecompositionDecl(C, DC, StartLoc, LSquareLoc, T, TInfo, SC, Bindings);
|
|
|
|
}
|
|
|
|
|
|
|
|
DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID,
|
|
|
|
unsigned NumBindings) {
|
|
|
|
size_t Extra = additionalSizeToAlloc<BindingDecl *>(NumBindings);
|
2016-08-12 10:21:25 +08:00
|
|
|
auto *Result = new (C, ID, Extra)
|
|
|
|
DecompositionDecl(C, nullptr, SourceLocation(), SourceLocation(),
|
|
|
|
QualType(), nullptr, StorageClass(), None);
|
2016-07-23 07:36:59 +08:00
|
|
|
// Set up and clean out the bindings array.
|
|
|
|
Result->NumBindings = NumBindings;
|
|
|
|
auto *Trail = Result->getTrailingObjects<BindingDecl *>();
|
|
|
|
for (unsigned I = 0; I != NumBindings; ++I)
|
|
|
|
new (Trail + I) BindingDecl*(nullptr);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2016-08-12 06:25:46 +08:00
|
|
|
void DecompositionDecl::printName(llvm::raw_ostream &os) const {
|
|
|
|
os << '[';
|
|
|
|
bool Comma = false;
|
2018-04-03 08:11:50 +08:00
|
|
|
for (const auto *B : bindings()) {
|
2016-08-12 06:25:46 +08:00
|
|
|
if (Comma)
|
|
|
|
os << ", ";
|
|
|
|
B->printName(os);
|
|
|
|
Comma = true;
|
|
|
|
}
|
|
|
|
os << ']';
|
|
|
|
}
|
|
|
|
|
2018-12-29 10:02:30 +08:00
|
|
|
void MSPropertyDecl::anchor() {}
|
|
|
|
|
2013-11-22 17:01:48 +08:00
|
|
|
MSPropertyDecl *MSPropertyDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation L, DeclarationName N,
|
|
|
|
QualType T, TypeSourceInfo *TInfo,
|
|
|
|
SourceLocation StartL,
|
|
|
|
IdentifierInfo *Getter,
|
|
|
|
IdentifierInfo *Setter) {
|
|
|
|
return new (C, DC) MSPropertyDecl(DC, L, N, T, TInfo, StartL, Getter, Setter);
|
|
|
|
}
|
|
|
|
|
|
|
|
MSPropertyDecl *MSPropertyDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
2014-05-12 13:36:57 +08:00
|
|
|
return new (C, ID) MSPropertyDecl(nullptr, SourceLocation(),
|
|
|
|
DeclarationName(), QualType(), nullptr,
|
|
|
|
SourceLocation(), nullptr, nullptr);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
Rework how UuidAttr, CXXUuidofExpr, and GUID template arguments and constants are represented.
Summary:
Previously, we treated CXXUuidofExpr as quite a special case: it was the
only kind of expression that could be a canonical template argument, it
could be a constant lvalue base object, and so on. In addition, we
represented the UUID value as a string, whose source form we did not
preserve faithfully, and that we partially parsed in multiple different
places.
With this patch, we create an MSGuidDecl object to represent the
implicit object of type 'struct _GUID' created by a UuidAttr. Each
UuidAttr holds a pointer to its 'struct _GUID' and its original
(as-written) UUID string. A non-value-dependent CXXUuidofExpr behaves
like a DeclRefExpr denoting that MSGuidDecl object. We cache an APValue
representation of the GUID on the MSGuidDecl and use it from constant
evaluation where needed.
This allows removing a lot of the special-case logic to handle these
expressions. Unfortunately, many parts of Clang assume there are only
a couple of interesting kinds of ValueDecl, so the total amount of
special-case logic is not really reduced very much.
This fixes a few bugs and issues:
* PR38490: we now support reading from GUID objects returned from
__uuidof during constant evaluation.
* Our Itanium mangling for a non-instantiation-dependent template
argument involving __uuidof no longer depends on which CXXUuidofExpr
template argument we happened to see first.
* We now predeclare ::_GUID, and permit use of __uuidof without
any header inclusion, better matching MSVC's behavior. We do not
predefine ::__s_GUID, though; that seems like a step too far.
* Our IR representation for GUID constants now uses the correct IR type
wherever possible. We will still fall back to using the
{i32, i16, i16, [8 x i8]}
layout if a definition of struct _GUID is not available. This is not
ideal: in principle the two layouts could have different padding.
Reviewers: rnk, jdoerfert
Subscribers: arphaman, cfe-commits, aeubanks
Tags: #clang
Differential Revision: https://reviews.llvm.org/D78171
2020-04-12 13:15:29 +08:00
|
|
|
void MSGuidDecl::anchor() {}
|
|
|
|
|
|
|
|
MSGuidDecl::MSGuidDecl(DeclContext *DC, QualType T, Parts P)
|
|
|
|
: ValueDecl(Decl::MSGuid, DC, SourceLocation(), DeclarationName(), T),
|
|
|
|
PartVal(P), APVal() {}
|
|
|
|
|
|
|
|
MSGuidDecl *MSGuidDecl::Create(const ASTContext &C, QualType T, Parts P) {
|
|
|
|
DeclContext *DC = C.getTranslationUnitDecl();
|
|
|
|
return new (C, DC) MSGuidDecl(DC, T, P);
|
|
|
|
}
|
|
|
|
|
|
|
|
MSGuidDecl *MSGuidDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
|
|
|
return new (C, ID) MSGuidDecl(nullptr, QualType(), Parts());
|
|
|
|
}
|
|
|
|
|
|
|
|
void MSGuidDecl::printName(llvm::raw_ostream &OS) const {
|
|
|
|
OS << llvm::format("GUID{%08" PRIx32 "-%04" PRIx16 "-%04" PRIx16 "-",
|
|
|
|
PartVal.Part1, PartVal.Part2, PartVal.Part3);
|
|
|
|
unsigned I = 0;
|
|
|
|
for (uint8_t Byte : PartVal.Part4And5) {
|
|
|
|
OS << llvm::format("%02" PRIx8, Byte);
|
|
|
|
if (++I == 2)
|
|
|
|
OS << '-';
|
|
|
|
}
|
|
|
|
OS << '}';
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Determine if T is a valid 'struct _GUID' of the shape that we expect.
|
|
|
|
static bool isValidStructGUID(ASTContext &Ctx, QualType T) {
|
|
|
|
// FIXME: We only need to check this once, not once each time we compute a
|
|
|
|
// GUID APValue.
|
|
|
|
using MatcherRef = llvm::function_ref<bool(QualType)>;
|
|
|
|
|
|
|
|
auto IsInt = [&Ctx](unsigned N) {
|
|
|
|
return [&Ctx, N](QualType T) {
|
|
|
|
return T->isUnsignedIntegerOrEnumerationType() &&
|
|
|
|
Ctx.getIntWidth(T) == N;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
auto IsArray = [&Ctx](MatcherRef Elem, unsigned N) {
|
|
|
|
return [&Ctx, Elem, N](QualType T) {
|
|
|
|
const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(T);
|
|
|
|
return CAT && CAT->getSize() == N && Elem(CAT->getElementType());
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
auto IsStruct = [](std::initializer_list<MatcherRef> Fields) {
|
|
|
|
return [Fields](QualType T) {
|
|
|
|
const RecordDecl *RD = T->getAsRecordDecl();
|
|
|
|
if (!RD || RD->isUnion())
|
|
|
|
return false;
|
|
|
|
RD = RD->getDefinition();
|
|
|
|
if (!RD)
|
|
|
|
return false;
|
|
|
|
if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
|
|
|
|
if (CXXRD->getNumBases())
|
|
|
|
return false;
|
|
|
|
auto MatcherIt = Fields.begin();
|
|
|
|
for (const FieldDecl *FD : RD->fields()) {
|
|
|
|
if (FD->isUnnamedBitfield()) continue;
|
|
|
|
if (FD->isBitField() || MatcherIt == Fields.end() ||
|
|
|
|
!(*MatcherIt)(FD->getType()))
|
|
|
|
return false;
|
|
|
|
++MatcherIt;
|
|
|
|
}
|
|
|
|
return MatcherIt == Fields.end();
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// We expect an {i32, i16, i16, [8 x i8]}.
|
|
|
|
return IsStruct({IsInt(32), IsInt(16), IsInt(16), IsArray(IsInt(8), 8)})(T);
|
|
|
|
}
|
|
|
|
|
|
|
|
APValue &MSGuidDecl::getAsAPValue() const {
|
|
|
|
if (APVal.isAbsent() && isValidStructGUID(getASTContext(), getType())) {
|
|
|
|
using llvm::APInt;
|
|
|
|
using llvm::APSInt;
|
|
|
|
APVal = APValue(APValue::UninitStruct(), 0, 4);
|
|
|
|
APVal.getStructField(0) = APValue(APSInt(APInt(32, PartVal.Part1), true));
|
|
|
|
APVal.getStructField(1) = APValue(APSInt(APInt(16, PartVal.Part2), true));
|
|
|
|
APVal.getStructField(2) = APValue(APSInt(APInt(16, PartVal.Part3), true));
|
|
|
|
APValue &Arr = APVal.getStructField(3) =
|
|
|
|
APValue(APValue::UninitArray(), 8, 8);
|
|
|
|
for (unsigned I = 0; I != 8; ++I) {
|
|
|
|
Arr.getArrayInitializedElt(I) =
|
|
|
|
APValue(APSInt(APInt(8, PartVal.Part4And5[I]), true));
|
|
|
|
}
|
2020-04-16 10:38:49 +08:00
|
|
|
// Register this APValue to be destroyed if necessary. (Note that the
|
|
|
|
// MSGuidDecl destructor is never run.)
|
|
|
|
getASTContext().addDestruction(&APVal);
|
Rework how UuidAttr, CXXUuidofExpr, and GUID template arguments and constants are represented.
Summary:
Previously, we treated CXXUuidofExpr as quite a special case: it was the
only kind of expression that could be a canonical template argument, it
could be a constant lvalue base object, and so on. In addition, we
represented the UUID value as a string, whose source form we did not
preserve faithfully, and that we partially parsed in multiple different
places.
With this patch, we create an MSGuidDecl object to represent the
implicit object of type 'struct _GUID' created by a UuidAttr. Each
UuidAttr holds a pointer to its 'struct _GUID' and its original
(as-written) UUID string. A non-value-dependent CXXUuidofExpr behaves
like a DeclRefExpr denoting that MSGuidDecl object. We cache an APValue
representation of the GUID on the MSGuidDecl and use it from constant
evaluation where needed.
This allows removing a lot of the special-case logic to handle these
expressions. Unfortunately, many parts of Clang assume there are only
a couple of interesting kinds of ValueDecl, so the total amount of
special-case logic is not really reduced very much.
This fixes a few bugs and issues:
* PR38490: we now support reading from GUID objects returned from
__uuidof during constant evaluation.
* Our Itanium mangling for a non-instantiation-dependent template
argument involving __uuidof no longer depends on which CXXUuidofExpr
template argument we happened to see first.
* We now predeclare ::_GUID, and permit use of __uuidof without
any header inclusion, better matching MSVC's behavior. We do not
predefine ::__s_GUID, though; that seems like a step too far.
* Our IR representation for GUID constants now uses the correct IR type
wherever possible. We will still fall back to using the
{i32, i16, i16, [8 x i8]}
layout if a definition of struct _GUID is not available. This is not
ideal: in principle the two layouts could have different padding.
Reviewers: rnk, jdoerfert
Subscribers: arphaman, cfe-commits, aeubanks
Tags: #clang
Differential Revision: https://reviews.llvm.org/D78171
2020-04-12 13:15:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return APVal;
|
|
|
|
}
|
|
|
|
|
2009-03-27 07:46:50 +08:00
|
|
|
static const char *getAccessName(AccessSpecifier AS) {
|
|
|
|
switch (AS) {
|
|
|
|
case AS_none:
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Invalid access specifier!");
|
2009-03-27 07:46:50 +08:00
|
|
|
case AS_public:
|
|
|
|
return "public";
|
|
|
|
case AS_private:
|
|
|
|
return "private";
|
|
|
|
case AS_protected:
|
|
|
|
return "protected";
|
|
|
|
}
|
2012-01-17 10:30:50 +08:00
|
|
|
llvm_unreachable("Invalid access specifier!");
|
2009-03-27 07:46:50 +08:00
|
|
|
}
|
|
|
|
|
2020-09-25 02:14:05 +08:00
|
|
|
const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
|
|
|
|
AccessSpecifier AS) {
|
|
|
|
return DB << getAccessName(AS);
|
|
|
|
}
|
|
|
|
|
|
|
|
const PartialDiagnostic &clang::operator<<(const PartialDiagnostic &DB,
|
|
|
|
AccessSpecifier AS) {
|
2012-02-02 09:16:57 +08:00
|
|
|
return DB << getAccessName(AS);
|
|
|
|
}
|