From 6515d877c0f32d143edd7565e4d10f0e0f3f41e2 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Sun, 24 Jan 2010 17:15:04 +0000 Subject: [PATCH] Fix a pretty bad bug where if a constructor (or conversion function) was marked as 'explicit', but then defined out-of-line, we would not treat it as being explicit. llvm-svn: 94366 --- clang/include/clang/AST/DeclCXX.h | 39 ++++++++++++++++++++++--------- clang/test/SemaCXX/explicit.cpp | 39 +++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 11 deletions(-) create mode 100644 clang/test/SemaCXX/explicit.cpp diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 73ebf52d383b..6692394b2d12 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1084,8 +1084,9 @@ public: /// }; /// @endcode class CXXConstructorDecl : public CXXMethodDecl { - /// Explicit - Whether this constructor is explicit. - bool Explicit : 1; + /// Explicit - Whether this constructor declaration has the + /// 'explicit' keyword specified. + bool IsExplicitSpecified : 1; /// ImplicitlyDefined - Whether this constructor was implicitly /// defined by the compiler. When false, the constructor was defined @@ -1103,9 +1104,10 @@ class CXXConstructorDecl : public CXXMethodDecl { CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - bool isExplicit, bool isInline, bool isImplicitlyDeclared) + bool isExplicitSpecified, bool isInline, + bool isImplicitlyDeclared) : CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false, isInline), - Explicit(isExplicit), ImplicitlyDefined(false), + IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false), BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) { setImplicit(isImplicitlyDeclared); } @@ -1118,8 +1120,15 @@ public: bool isExplicit, bool isInline, bool isImplicitlyDeclared); + /// isExplicitSpecified - Whether this constructor declaration has the + /// 'explicit' keyword specified. + bool isExplicitSpecified() const { return IsExplicitSpecified; } + /// isExplicit - Whether this constructor was marked "explicit" or not. - bool isExplicit() const { return Explicit; } + bool isExplicit() const { + return cast(getFirstDeclaration()) + ->isExplicitSpecified(); + } /// isImplicitlyDefined - Whether this constructor was implicitly /// defined. If false, then this constructor was defined by the @@ -1290,16 +1299,16 @@ public: /// }; /// @endcode class CXXConversionDecl : public CXXMethodDecl { - /// Explicit - Whether this conversion function is marked - /// "explicit", meaning that it can only be applied when the user + /// IsExplicitSpecified - Whether this conversion function declaration is + /// marked "explicit", meaning that it can only be applied when the user /// explicitly wrote a cast. This is a C++0x feature. - bool Explicit : 1; + bool IsExplicitSpecified : 1; CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isExplicit) + bool isInline, bool isExplicitSpecified) : CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false, isInline), - Explicit(isExplicit) { } + IsExplicitSpecified(isExplicitSpecified) { } public: static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, @@ -1307,10 +1316,18 @@ public: QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicit); + /// IsExplicitSpecified - Whether this conversion function declaration is + /// marked "explicit", meaning that it can only be applied when the user + /// explicitly wrote a cast. This is a C++0x feature. + bool isExplicitSpecified() const { return IsExplicitSpecified; } + /// isExplicit - Whether this is an explicit conversion operator /// (C++0x only). Explicit conversion operators are only considered /// when the user has explicitly written a cast. - bool isExplicit() const { return Explicit; } + bool isExplicit() const { + return cast(getFirstDeclaration()) + ->isExplicitSpecified(); + } /// getConversionType - Returns the type that this conversion /// function is converting to. diff --git a/clang/test/SemaCXX/explicit.cpp b/clang/test/SemaCXX/explicit.cpp new file mode 100644 index 000000000000..717ed1e3caf2 --- /dev/null +++ b/clang/test/SemaCXX/explicit.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +namespace Constructor { +struct A { + A(int); +}; + +struct B { + explicit B(int); +}; + +B::B(int) { } + +struct C { + void f(const A&); + void f(const B&); +}; + +void f(C c) { + c.f(10); +} +} + +namespace Conversion { + struct A { + operator int(); + explicit operator bool(); + }; + + A::operator bool() { return false; } + + struct B { + void f(int); + void f(bool); + }; + + void f(A a, B b) { + b.f(a); + } +}