summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorNicolas Lesser <blitzrakete@gmail.com>2019-05-04 00:09:00 +0000
committerNicolas Lesser <blitzrakete@gmail.com>2019-05-04 00:09:00 +0000
commit6de0b449c07ec7adbcb34e7c94c544ee37ef5963 (patch)
tree0e2112dbbe57b79622f5a7708add8fecc6a75b80 /include
parent6cc60c9164a96f1d73ccfd302303490e0d085b87 (diff)
[clang] adding explicit(bool) from c++2a
this patch adds support for the explicit bool specifier. Changes: - The parsing for the explicit(bool) specifier was added in ParseDecl.cpp. - The storage of the explicit specifier was changed. the explicit specifier was stored as a boolean value in the FunctionDeclBitfields and in the DeclSpec class. now it is stored as a PointerIntPair<Expr*, 2> with a flag and a potential expression in CXXConstructorDecl, CXXDeductionGuideDecl, CXXConversionDecl and in the DeclSpec class. - Following the AST change, Serialization, ASTMatchers, ASTComparator and ASTPrinter were adapted. - Template instantiation was adapted to instantiate the potential expressions of the explicit(bool) specifier When instantiating their associated declaration. - The Add*Candidate functions were adapted, they now take a Boolean indicating if the context allowing explicit constructor or conversion function and this boolean is used to remove invalid overloads that required template instantiation to be detected. - Test for Semantic and Serialization were added. This patch is not yet complete. I still need to check that interaction with CTAD and deduction guides is correct. and add more tests for AST operations. But I wanted first feedback. Perhaps this patch should be spited in smaller patches, but making each patch testable as a standalone may be tricky. Patch by Tyker Differential Revision: https://reviews.llvm.org/D60934 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@359949 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r--include/clang/AST/Decl.h10
-rw-r--r--include/clang/AST/DeclBase.h20
-rw-r--r--include/clang/AST/DeclCXX.h176
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h3
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td2
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td4
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td13
-rw-r--r--include/clang/Basic/Specifiers.h8
-rw-r--r--include/clang/Sema/DeclSpec.h62
-rw-r--r--include/clang/Sema/Overload.h5
-rw-r--r--include/clang/Sema/Sema.h38
-rw-r--r--include/clang/Serialization/ASTBitCodes.h3
-rw-r--r--include/clang/Serialization/ASTReader.h8
13 files changed, 241 insertions, 111 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index da8128937e..cfb9ff8948 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -2369,16 +2369,6 @@ public:
/// that was defined in the class body.
bool isInlined() const { return FunctionDeclBits.IsInline; }
- /// Whether this function is marked as explicit explicitly.
- bool isExplicitSpecified() const {
- return FunctionDeclBits.IsExplicitSpecified;
- }
-
- /// State that this function is marked as explicit explicitly.
- void setExplicitSpecified(bool ExpSpec = true) {
- FunctionDeclBits.IsExplicitSpecified = ExpSpec;
- }
-
bool isInlineDefinitionExternallyVisible() const;
bool isMSExternInline() const;
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 64adf304c6..ad283a6bc1 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -1472,10 +1472,6 @@ class DeclContext {
uint64_t IsInline : 1;
uint64_t IsInlineSpecified : 1;
- /// This is shared by CXXConstructorDecl,
- /// CXXConversionDecl, and CXXDeductionGuideDecl.
- uint64_t IsExplicitSpecified : 1;
-
uint64_t IsVirtualAsWritten : 1;
uint64_t IsPure : 1;
uint64_t HasInheritedPrototype : 1;
@@ -1523,7 +1519,7 @@ class DeclContext {
};
/// Number of non-inherited bits in FunctionDeclBitfields.
- enum { NumFunctionDeclBits = 25 };
+ enum { NumFunctionDeclBits = 24 };
/// Stores the bits used by CXXConstructorDecl. If modified
/// NumCXXConstructorDeclBits and the accessor
@@ -1535,17 +1531,25 @@ class DeclContext {
/// For the bits in FunctionDeclBitfields.
uint64_t : NumFunctionDeclBits;
- /// 25 bits to fit in the remaining availible space.
+ /// 24 bits to fit in the remaining available space.
/// Note that this makes CXXConstructorDeclBitfields take
/// exactly 64 bits and thus the width of NumCtorInitializers
/// will need to be shrunk if some bit is added to NumDeclContextBitfields,
/// NumFunctionDeclBitfields or CXXConstructorDeclBitfields.
- uint64_t NumCtorInitializers : 25;
+ uint64_t NumCtorInitializers : 24;
uint64_t IsInheritingConstructor : 1;
+
+ /// Whether this constructor has a trail-allocated explicit specifier.
+ uint64_t HasTrailingExplicitSpecifier : 1;
+ /// If this constructor does't have a trail-allocated explicit specifier.
+ /// Whether this constructor is explicit specified.
+ uint64_t IsSimpleExplicit : 1;
};
/// Number of non-inherited bits in CXXConstructorDeclBitfields.
- enum { NumCXXConstructorDeclBits = 26 };
+ enum {
+ NumCXXConstructorDeclBits = 64 - NumDeclContextBits - NumFunctionDeclBits
+ };
/// Stores the bits used by ObjCMethodDecl.
/// If modified NumObjCMethodDeclBits and the accessor
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index a1717e6273..5a9e418a2c 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -1990,6 +1990,50 @@ public:
}
};
+/// Store information needed for an explicit specifier.
+/// used by CXXDeductionGuideDecl, CXXConstructorDecl and CXXConversionDecl.
+class ExplicitSpecifier {
+ llvm::PointerIntPair<Expr *, 2, ExplicitSpecKind> ExplicitSpec{
+ nullptr, ExplicitSpecKind::ResolvedFalse};
+
+public:
+ ExplicitSpecifier() = default;
+ ExplicitSpecifier(Expr *Expression, ExplicitSpecKind Kind)
+ : ExplicitSpec(Expression, Kind) {}
+ ExplicitSpecKind getKind() const { return ExplicitSpec.getInt(); }
+ const Expr *getExpr() const { return ExplicitSpec.getPointer(); }
+ Expr *getExpr() { return ExplicitSpec.getPointer(); }
+
+ /// Return true if the ExplicitSpecifier isn't defaulted.
+ bool isSpecified() const {
+ return ExplicitSpec.getInt() != ExplicitSpecKind::ResolvedFalse ||
+ ExplicitSpec.getPointer();
+ }
+
+ /// Check for Equivalence of explicit specifiers.
+ /// Return True if the explicit specifier are equivalent false otherwise.
+ bool isEquivalent(const ExplicitSpecifier Other) const;
+ /// Return true if the explicit specifier is already resolved to be explicit.
+ bool isExplicit() const {
+ return ExplicitSpec.getInt() == ExplicitSpecKind::ResolvedTrue;
+ }
+ /// Return true if the ExplicitSpecifier isn't valid.
+ /// This state occurs after a substitution failures.
+ bool isInvalid() const {
+ return ExplicitSpec.getInt() == ExplicitSpecKind::Unresolved &&
+ !ExplicitSpec.getPointer();
+ }
+ void setKind(ExplicitSpecKind Kind) { ExplicitSpec.setInt(Kind); }
+ void setExpr(Expr *E) { ExplicitSpec.setPointer(E); }
+ // getFromDecl - retrieve the explicit specifier in the given declaration.
+ // if the given declaration has no explicit. the returned explicit specifier
+ // is defaulted. .isSpecified() will be false.
+ static ExplicitSpecifier getFromDecl(FunctionDecl *Function);
+ static ExplicitSpecifier Invalid() {
+ return ExplicitSpecifier(nullptr, ExplicitSpecKind::Unresolved);
+ }
+};
+
/// Represents a C++ deduction guide declaration.
///
/// \code
@@ -2005,31 +2049,36 @@ class CXXDeductionGuideDecl : public FunctionDecl {
private:
CXXDeductionGuideDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
- bool IsExplicit, const DeclarationNameInfo &NameInfo,
- QualType T, TypeSourceInfo *TInfo,
- SourceLocation EndLocation)
+ ExplicitSpecifier ES,
+ const DeclarationNameInfo &NameInfo, QualType T,
+ TypeSourceInfo *TInfo, SourceLocation EndLocation)
: FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo,
- SC_None, false, false) {
+ SC_None, false, false),
+ ExplicitSpec(ES) {
if (EndLocation.isValid())
setRangeEnd(EndLocation);
- setExplicitSpecified(IsExplicit);
setIsCopyDeductionCandidate(false);
}
+ ExplicitSpecifier ExplicitSpec;
+ void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; }
+
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
- static CXXDeductionGuideDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation StartLoc, bool IsExplicit,
- const DeclarationNameInfo &NameInfo,
- QualType T, TypeSourceInfo *TInfo,
- SourceLocation EndLocation);
+ static CXXDeductionGuideDecl *
+ Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
+ ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T,
+ TypeSourceInfo *TInfo, SourceLocation EndLocation);
static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- /// Whether this deduction guide is explicit.
- bool isExplicit() const { return isExplicitSpecified(); }
+ ExplicitSpecifier getExplicitSpecifier() { return ExplicitSpec; }
+ const ExplicitSpecifier getExplicitSpecifier() const { return ExplicitSpec; }
+
+ /// Return true if the declartion is already resolved to be explicit.
+ bool isExplicit() const { return ExplicitSpec.isExplicit(); }
/// Get the template for which this guide performs deduction.
TemplateDecl *getDeducedTemplate() const {
@@ -2498,7 +2547,8 @@ public:
/// \endcode
class CXXConstructorDecl final
: public CXXMethodDecl,
- private llvm::TrailingObjects<CXXConstructorDecl, InheritedConstructor> {
+ private llvm::TrailingObjects<CXXConstructorDecl, InheritedConstructor,
+ ExplicitSpecifier> {
// This class stores some data in DeclContext::CXXConstructorDeclBits
// to save some space. Use the provided accessors to access it.
@@ -2508,28 +2558,74 @@ class CXXConstructorDecl final
LazyCXXCtorInitializersPtr CtorInitializers;
CXXConstructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
- const DeclarationNameInfo &NameInfo,
- QualType T, TypeSourceInfo *TInfo,
- bool isExplicitSpecified, bool isInline,
+ const DeclarationNameInfo &NameInfo, QualType T,
+ TypeSourceInfo *TInfo, ExplicitSpecifier ES, bool isInline,
bool isImplicitlyDeclared, bool isConstexpr,
InheritedConstructor Inherited);
void anchor() override;
+ size_t numTrailingObjects(OverloadToken<InheritedConstructor>) const {
+ return CXXConstructorDeclBits.IsInheritingConstructor;
+ }
+ size_t numTrailingObjects(OverloadToken<ExplicitSpecifier>) const {
+ return CXXConstructorDeclBits.HasTrailingExplicitSpecifier;
+ }
+
+ ExplicitSpecifier getExplicitSpecifierInternal() const {
+ if (CXXConstructorDeclBits.HasTrailingExplicitSpecifier)
+ return *getCanonicalDecl()->getTrailingObjects<ExplicitSpecifier>();
+ return ExplicitSpecifier(
+ nullptr, getCanonicalDecl()->CXXConstructorDeclBits.IsSimpleExplicit
+ ? ExplicitSpecKind::ResolvedTrue
+ : ExplicitSpecKind::ResolvedFalse);
+ }
+
+ void setExplicitSpecifier(ExplicitSpecifier ES) {
+ assert((!ES.getExpr() ||
+ CXXConstructorDeclBits.HasTrailingExplicitSpecifier) &&
+ "cannot set this explicit specifier. no trail-allocated space for "
+ "explicit");
+ if (ES.getExpr())
+ *getCanonicalDecl()->getTrailingObjects<ExplicitSpecifier>() = ES;
+ else
+ CXXConstructorDeclBits.IsSimpleExplicit = ES.isExplicit();
+ }
+
+ enum TraillingAllocKind {
+ TAKInheritsConstructor = 1,
+ TAKHasTailExplicit = 1 << 1,
+ };
+
+ uint64_t getTraillingAllocKind() const {
+ return numTrailingObjects(OverloadToken<InheritedConstructor>()) |
+ (numTrailingObjects(OverloadToken<ExplicitSpecifier>()) << 1);
+ }
+
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
friend TrailingObjects;
static CXXConstructorDecl *CreateDeserialized(ASTContext &C, unsigned ID,
- bool InheritsConstructor);
+ uint64_t AllocKind);
static CXXConstructorDecl *
Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
- bool isExplicit, bool isInline, bool isImplicitlyDeclared,
+ ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared,
bool isConstexpr,
InheritedConstructor Inherited = InheritedConstructor());
+ ExplicitSpecifier getExplicitSpecifier() {
+ return getExplicitSpecifierInternal();
+ }
+ const ExplicitSpecifier getExplicitSpecifier() const {
+ return getExplicitSpecifierInternal();
+ }
+
+ /// Return true if the declartion is already resolved to be explicit.
+ bool isExplicit() const { return getExplicitSpecifier().isExplicit(); }
+
/// Iterates through the member/base initializer list.
using init_iterator = CXXCtorInitializer **;
@@ -2600,11 +2696,6 @@ public:
CtorInitializers = Initializers;
}
- /// Whether this function is explicit.
- bool isExplicit() const {
- return getCanonicalDecl()->isExplicitSpecified();
- }
-
/// Determine whether this constructor is a delegating constructor.
bool isDelegatingConstructor() const {
return (getNumCtorInitializers() == 1) &&
@@ -2783,34 +2874,39 @@ public:
class CXXConversionDecl : public CXXMethodDecl {
CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo, QualType T,
- TypeSourceInfo *TInfo, bool isInline,
- bool isExplicitSpecified, bool isConstexpr,
- SourceLocation EndLocation)
+ TypeSourceInfo *TInfo, bool isInline, ExplicitSpecifier ES,
+ bool isConstexpr, SourceLocation EndLocation)
: CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo,
- SC_None, isInline, isConstexpr, EndLocation) {
- setExplicitSpecified(isExplicitSpecified);
- }
-
+ SC_None, isInline, isConstexpr, EndLocation),
+ ExplicitSpec(ES) {}
void anchor() override;
+ ExplicitSpecifier ExplicitSpec;
+
+ void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; }
+
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
- static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation StartLoc,
- const DeclarationNameInfo &NameInfo,
- QualType T, TypeSourceInfo *TInfo,
- bool isInline, bool isExplicit,
- bool isConstexpr,
- SourceLocation EndLocation);
+ static CXXConversionDecl *
+ Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
+ bool isInline, ExplicitSpecifier ES, bool isConstexpr,
+ SourceLocation EndLocation);
static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- /// Whether this function is explicit.
- bool isExplicit() const {
- return getCanonicalDecl()->isExplicitSpecified();
+ ExplicitSpecifier getExplicitSpecifier() {
+ return getCanonicalDecl()->ExplicitSpec;
}
+ const ExplicitSpecifier getExplicitSpecifier() const {
+ return getCanonicalDecl()->ExplicitSpec;
+ }
+
+ /// Return true if the declartion is already resolved to be explicit.
+ bool isExplicit() const { return getExplicitSpecifier().isExplicit(); }
+
/// Returns the type that this conversion function is converting to.
QualType getConversionType() const {
return getType()->getAs<FunctionType>()->getReturnType();
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 8bd4429f0b..57dff7993d 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -6171,6 +6171,9 @@ AST_MATCHER(CXXConstructorDecl, isDelegatingConstructor) {
AST_POLYMORPHIC_MATCHER(isExplicit,
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXConstructorDecl,
CXXConversionDecl)) {
+ // FIXME : it's not clear whether this should match a dependent
+ // explicit(....). this matcher should also be able to match
+ // CXXDeductionGuideDecl with explicit specifier.
return Node.isExplicit();
}
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index 7cd3b21109..0727980751 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -150,6 +150,8 @@ def ext_warn_duplicate_declspec : ExtWarn<"%sub{duplicate_declspec}0">,
def warn_duplicate_declspec : Warning<"%sub{duplicate_declspec}0">,
InGroup<DuplicateDeclSpecifier>;
+def err_duplicate_declspec : Error<"%sub{duplicate_declspec}0">;
+
def err_friend_decl_spec : Error<"'%0' is invalid in friend declarations">;
def err_invalid_member_in_interface : Error<
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 4bd29b629d..8b9d6cdd7a 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -33,6 +33,10 @@ def err_asm_goto_not_supported_yet : Error<
let CategoryName = "Parse Issue" in {
+def warn_cxx2a_compat_explicit_bool : Warning<
+ "this expression will be parsed as explicit(bool) in C++2a">,
+ InGroup<CXX2aCompat>, DefaultIgnore;
+
def ext_empty_translation_unit : Extension<
"ISO C requires a translation unit to contain at least one declaration">,
InGroup<DiagGroup<"empty-translation-unit">>;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index cccc9e4aa0..84145c1d32 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -83,11 +83,11 @@ def err_typecheck_converted_constant_expression_indirect : Error<
"bind reference to a temporary">;
def err_expr_not_cce : Error<
"%select{case value|enumerator value|non-type template argument|"
- "array size|constexpr if condition}0 "
+ "array size|constexpr if condition|explicit specifier argument}0 "
"is not a constant expression">;
def ext_cce_narrowing : ExtWarn<
"%select{case value|enumerator value|non-type template argument|"
- "array size|constexpr if condition}0 "
+ "array size|constexpr if condition|explicit specifier argument}0 "
"%select{cannot be narrowed from type %2 to %3|"
"evaluates to %2, which cannot be narrowed to type %3}1">,
InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
@@ -2115,9 +2115,8 @@ def err_deduction_guide_wrong_scope : Error<
"deduction guide must be declared in the same scope as template %q0">;
def err_deduction_guide_defines_function : Error<
"deduction guide cannot have a function definition">;
-def err_deduction_guide_explicit_mismatch : Error<
- "deduction guide is %select{not |}0declared 'explicit' but "
- "previous declaration was%select{ not|}0">;
+def err_deduction_guide_redeclared : Error<
+ "redeclaration of deduction guide">;
def err_deduction_guide_specialized : Error<"deduction guide cannot be "
"%select{explicitly instantiated|explicitly specialized}0">;
def err_deduction_guide_template_not_deducible : Error<
@@ -3640,6 +3639,10 @@ def note_ovl_candidate : Note<
"| has different qualifiers (expected %5 but found %6)"
"| has different exception specification}4">;
+def note_ovl_candidate_explicit_forbidden : Note<
+ "candidate %0 ignored: cannot be explicit">;
+def note_explicit_bool_resolved_to_true : Note<
+ "explicit(bool) specifier resolved to true">;
def note_ovl_candidate_inherited_constructor : Note<
"constructor from base class %0 inherited here">;
def note_ovl_candidate_inherited_constructor_slice : Note<
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index 7256acafde..cc0c1c82df 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -20,6 +20,14 @@
#include "llvm/Support/ErrorHandling.h"
namespace clang {
+
+ /// Define the meaning of possible values of the kind in ExplicitSpecifier.
+ enum class ExplicitSpecKind : unsigned {
+ ResolvedFalse,
+ ResolvedTrue,
+ Unresolved,
+ };
+
/// Specifies the width of a type, e.g., short, long, or long long.
enum TypeSpecifierWidth {
TSW_unspecified,
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index babdc9d8f7..f1c2a67400 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -22,6 +22,7 @@
#ifndef LLVM_CLANG_SEMA_DECLSPEC_H
#define LLVM_CLANG_SEMA_DECLSPEC_H
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/Lambda.h"
@@ -356,7 +357,6 @@ private:
unsigned FS_inline_specified : 1;
unsigned FS_forceinline_specified: 1;
unsigned FS_virtual_specified : 1;
- unsigned FS_explicit_specified : 1;
unsigned FS_noreturn_specified : 1;
// friend-specifier
@@ -371,6 +371,9 @@ private:
Expr *ExprRep;
};
+ /// ExplicitSpecifier - Store information about explicit spicifer.
+ ExplicitSpecifier FS_explicit_specifier;
+
// attributes.
ParsedAttributes Attrs;
@@ -393,6 +396,7 @@ private:
SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc,
TQ_unalignedLoc;
SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc;
+ SourceLocation FS_explicitCloseParenLoc;
SourceLocation FS_forceinlineLoc;
SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc;
SourceLocation TQ_pipeLoc;
@@ -420,31 +424,18 @@ public:
}
DeclSpec(AttributeFactory &attrFactory)
- : StorageClassSpec(SCS_unspecified),
- ThreadStorageClassSpec(TSCS_unspecified),
- SCS_extern_in_linkage_spec(false),
- TypeSpecWidth(TSW_unspecified),
- TypeSpecComplex(TSC_unspecified),
- TypeSpecSign(TSS_unspecified),
- TypeSpecType(TST_unspecified),
- TypeAltiVecVector(false),
- TypeAltiVecPixel(false),
- TypeAltiVecBool(false),
- TypeSpecOwned(false),
- TypeSpecPipe(false),
- TypeSpecSat(false),
- TypeQualifiers(TQ_unspecified),
- FS_inline_specified(false),
- FS_forceinline_specified(false),
- FS_virtual_specified(false),
- FS_explicit_specified(false),
- FS_noreturn_specified(false),
- Friend_specified(false),
- Constexpr_specified(false),
- Attrs(attrFactory),
- writtenBS(),
- ObjCQualifiers(nullptr) {
- }
+ : StorageClassSpec(SCS_unspecified),
+ ThreadStorageClassSpec(TSCS_unspecified),
+ SCS_extern_in_linkage_spec(false), TypeSpecWidth(TSW_unspecified),
+ TypeSpecComplex(TSC_unspecified), TypeSpecSign(TSS_unspecified),
+ TypeSpecType(TST_unspecified), TypeAltiVecVector(false),
+ TypeAltiVecPixel(false), TypeAltiVecBool(false), TypeSpecOwned(false),
+ TypeSpecPipe(false), TypeSpecSat(false), TypeQualifiers(TQ_unspecified),
+ FS_inline_specified(false), FS_forceinline_specified(false),
+ FS_virtual_specified(false), FS_noreturn_specified(false),
+ Friend_specified(false), Constexpr_specified(false),
+ FS_explicit_specifier(), Attrs(attrFactory), writtenBS(),
+ ObjCQualifiers(nullptr) {}
// storage-class-specifier
SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; }
@@ -570,11 +561,22 @@ public:
return FS_inline_specified ? FS_inlineLoc : FS_forceinlineLoc;
}
+ ExplicitSpecifier getExplicitSpecifier() const {
+ return FS_explicit_specifier;
+ }
+
bool isVirtualSpecified() const { return FS_virtual_specified; }
SourceLocation getVirtualSpecLoc() const { return FS_virtualLoc; }
- bool isExplicitSpecified() const { return FS_explicit_specified; }
+ bool hasExplicitSpecifier() const {
+ return FS_explicit_specifier.isSpecified();
+ }
SourceLocation getExplicitSpecLoc() const { return FS_explicitLoc; }
+ SourceRange getExplicitSpecRange() const {
+ return FS_explicit_specifier.getExpr()
+ ? SourceRange(FS_explicitLoc, FS_explicitCloseParenLoc)
+ : SourceRange(FS_explicitLoc);
+ }
bool isNoreturnSpecified() const { return FS_noreturn_specified; }
SourceLocation getNoreturnSpecLoc() const { return FS_noreturnLoc; }
@@ -586,8 +588,9 @@ public:
FS_forceinlineLoc = SourceLocation();
FS_virtual_specified = false;
FS_virtualLoc = SourceLocation();
- FS_explicit_specified = false;
+ FS_explicit_specifier = ExplicitSpecifier();
FS_explicitLoc = SourceLocation();
+ FS_explicitCloseParenLoc = SourceLocation();
FS_noreturn_specified = false;
FS_noreturnLoc = SourceLocation();
}
@@ -706,7 +709,8 @@ public:
bool setFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID);
bool setFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID);
+ unsigned &DiagID, ExplicitSpecifier ExplicitSpec,
+ SourceLocation CloseParenLoc);
bool setFunctionSpecNoreturn(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID);
diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h
index 342ce0f026..cacb592b18 100644
--- a/include/clang/Sema/Overload.h
+++ b/include/clang/Sema/Overload.h
@@ -705,6 +705,11 @@ class Sema;
/// attribute disabled it.
ovl_fail_enable_if,
+ /// This candidate constructor or conversion fonction
+ /// is used implicitly but the explicit(bool) specifier
+ /// was resolved to true
+ ovl_fail_explicit_resolved,
+
/// This candidate was not viable because its address could not be taken.
ovl_fail_addr_not_available,
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 93932b4ff6..91a0cfd317 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2744,7 +2744,8 @@ public:
CCEK_Enumerator, ///< Enumerator value with fixed underlying type.
CCEK_TemplateArg, ///< Value of a non-type template parameter.
CCEK_NewExpr, ///< Constant expression in a noptr-new-declarator.
- CCEK_ConstexprIf ///< Condition in a constexpr if statement.
+ CCEK_ConstexprIf, ///< Condition in a constexpr if statement.
+ CCEK_ExplicitBool ///< Condition in an explicit(bool) specifier.
};
ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
llvm::APSInt &Value, CCEKind CCE);
@@ -2867,6 +2868,7 @@ public:
bool SuppressUserConversions = false,
bool PartialOverloading = false,
bool AllowExplicit = false,
+ bool AllowExplicitConversion = false,
ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
ConversionSequenceList EarlyConversions = None);
void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
@@ -2905,7 +2907,7 @@ public:
FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
- bool PartialOverloading = false,
+ bool PartialOverloading = false, bool AllowExplicit = false,
ADLCallKind IsADLCandidate = ADLCallKind::NotADL);
bool CheckNonDependentConversions(FunctionTemplateDecl *FunctionTemplate,
ArrayRef<QualType> ParamTypes,
@@ -2917,20 +2919,16 @@ public:
QualType ObjectType = QualType(),
Expr::Classification
ObjectClassification = {});
- void AddConversionCandidate(CXXConversionDecl *Conversion,
- DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingContext,
- Expr *From, QualType ToType,
- OverloadCandidateSet& CandidateSet,
- bool AllowObjCConversionOnExplicit,
- bool AllowResultConversion = true);
- void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
- DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingContext,
- Expr *From, QualType ToType,
- OverloadCandidateSet &CandidateSet,
- bool AllowObjCConversionOnExplicit,
- bool AllowResultConversion = true);
+ void AddConversionCandidate(
+ CXXConversionDecl *Conversion, DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
+ OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
+ bool AllowExplicit, bool AllowResultConversion = true);
+ void AddTemplateConversionCandidate(
+ FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
+ OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
+ bool AllowExplicit, bool AllowResultConversion = true);
void AddSurrogateCandidate(CXXConversionDecl *Conversion,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
@@ -10120,6 +10118,14 @@ public:
ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E,
bool IsConstexpr = false);
+ /// ActOnExplicitBoolSpecifier - Build an ExplicitSpecifier from an expression
+ /// found in an explicit(bool) specifier.
+ ExplicitSpecifier ActOnExplicitBoolSpecifier(Expr *E);
+
+ /// tryResolveExplicitSpecifier - Attempt to resolve the explict specifier.
+ /// Returns true if the explicit specifier is now resolved.
+ bool tryResolveExplicitSpecifier(ExplicitSpecifier &ExplicitSpec);
+
/// DiagnoseAssignmentAsCondition - Given that an expression is
/// being used as a boolean condition, warn if it's an assignment.
void DiagnoseAssignmentAsCondition(Expr *E);
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 0365e3a696..b38b6b034d 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -1438,9 +1438,6 @@ namespace serialization {
/// A CXXConstructorDecl record.
DECL_CXX_CONSTRUCTOR,
- /// A CXXConstructorDecl record for an inherited constructor.
- DECL_CXX_INHERITED_CONSTRUCTOR,
-
/// A CXXDestructorDecl record.
DECL_CXX_DESTRUCTOR,
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 423313ea56..579cdc1bff 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -2430,6 +2430,14 @@ public:
ID);
}
+ ExplicitSpecifier readExplicitSpec() {
+ uint64_t Kind = readInt();
+ bool HasExpr = Kind & 0x1;
+ Kind = Kind >> 1;
+ return ExplicitSpecifier(HasExpr ? readExpr() : nullptr,
+ static_cast<ExplicitSpecKind>(Kind));
+ }
+
void readExceptionSpec(SmallVectorImpl<QualType> &ExceptionStorage,
FunctionProtoType::ExceptionSpecInfo &ESI) {
return Reader->readExceptionSpec(*F, ExceptionStorage, ESI, Record, Idx);