aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/DeclCXX.h4
-rw-r--r--lib/AST/CXXInheritance.cpp9
-rw-r--r--lib/Sema/SemaExprCXX.cpp47
-rw-r--r--test/SemaCXX/type-traits.cpp12
4 files changed, 46 insertions, 26 deletions
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 8c66752f42..1d1b749feb 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -811,7 +811,7 @@ public:
/// \param Base the base class we are searching for.
///
/// \returns true if this class is derived from Base, false otherwise.
- bool isDerivedFrom(CXXRecordDecl *Base) const;
+ bool isDerivedFrom(const CXXRecordDecl *Base) const;
/// \brief Determine whether this class is derived from the type \p Base.
///
@@ -829,7 +829,7 @@ public:
///
/// \todo add a separate paramaeter to configure IsDerivedFrom, rather than
/// tangling input and output in \p Paths
- bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const;
+ bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths) const;
/// \brief Determine whether this class is virtually derived from
/// the class \p Base.
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index 9853fc2bb2..ca9ec18b39 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/lib/AST/CXXInheritance.cpp
@@ -76,18 +76,21 @@ void CXXBasePaths::swap(CXXBasePaths &Other) {
std::swap(DetectedVirtual, Other.DetectedVirtual);
}
-bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base) const {
+bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base) const {
CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false,
/*DetectVirtual=*/false);
return isDerivedFrom(Base, Paths);
}
-bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const {
+bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base,
+ CXXBasePaths &Paths) const {
if (getCanonicalDecl() == Base->getCanonicalDecl())
return false;
Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
- return lookupInBases(&FindBaseClass, Base->getCanonicalDecl(), Paths);
+ return lookupInBases(&FindBaseClass,
+ const_cast<CXXRecordDecl*>(Base->getCanonicalDecl()),
+ Paths);
}
bool CXXRecordDecl::isVirtuallyDerivedFrom(CXXRecordDecl *Base) const {
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 6ba18a54fd..82e818fba0 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -2487,17 +2487,36 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,
"Cannot evaluate traits for dependent types.");
switch(BTT) {
- case BTT_IsBaseOf:
+ case BTT_IsBaseOf: {
// C++0x [meta.rel]p2
- // Base is a base class of Derived without regard to cv-qualifiers or
+ // Base is a base class of Derived without regard to cv-qualifiers or
// Base and Derived are not unions and name the same class type without
// regard to cv-qualifiers.
- if (Self.IsDerivedFrom(RhsT, LhsT) ||
- (!LhsT->isUnionType() && !RhsT->isUnionType()
- && LhsT->getAsCXXRecordDecl() == RhsT->getAsCXXRecordDecl()))
- return true;
- return false;
+ const RecordType *lhsRecord = LhsT->getAs<RecordType>();
+ if (!lhsRecord) return false;
+
+ const RecordType *rhsRecord = RhsT->getAs<RecordType>();
+ if (!rhsRecord) return false;
+
+ assert(Self.Context.hasSameUnqualifiedType(LhsT, RhsT)
+ == (lhsRecord == rhsRecord));
+
+ if (lhsRecord == rhsRecord)
+ return !lhsRecord->getDecl()->isUnion();
+
+ // C++0x [meta.rel]p2:
+ // If Base and Derived are class types and are different types
+ // (ignoring possible cv-qualifiers) then Derived shall be a
+ // complete type.
+ if (Self.RequireCompleteType(KeyLoc, RhsT,
+ diag::err_incomplete_type_used_in_type_trait_expr))
+ return false;
+
+ return cast<CXXRecordDecl>(rhsRecord->getDecl())
+ ->isDerivedFrom(cast<CXXRecordDecl>(lhsRecord->getDecl()));
+ }
+
case BTT_TypeCompatible:
return Self.Context.typesAreCompatible(LhsT.getUnqualifiedType(),
RhsT.getUnqualifiedType());
@@ -2560,19 +2579,7 @@ ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT,
QualType LhsT = LhsTSInfo->getType();
QualType RhsT = RhsTSInfo->getType();
- if (BTT == BTT_IsBaseOf) {
- // C++0x [meta.rel]p2
- // If Base and Derived are class types and are different types
- // (ignoring possible cv-qualifiers) then Derived shall be a complete
- // type. []
- CXXRecordDecl *LhsDecl = LhsT->getAsCXXRecordDecl();
- CXXRecordDecl *RhsDecl = RhsT->getAsCXXRecordDecl();
- if (!LhsT->isDependentType() && !RhsT->isDependentType() &&
- LhsDecl && RhsDecl && LhsT != RhsT &&
- RequireCompleteType(KWLoc, RhsT,
- diag::err_incomplete_type_used_in_type_trait_expr))
- return ExprError();
- } else if (BTT == BTT_TypeCompatible) {
+ if (BTT == BTT_TypeCompatible) {
if (getLangOptions().CPlusPlus) {
Diag(KWLoc, diag::err_types_compatible_p_in_cplusplus)
<< SourceRange(KWLoc, RParen);
diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp
index b7f18aa6bd..ff9a6bf51a 100644
--- a/test/SemaCXX/type-traits.cpp
+++ b/test/SemaCXX/type-traits.cpp
@@ -469,6 +469,9 @@ void isBaseOfF() {
int t[F(__is_base_of(Base, Derived))];
};
+template <class T> class DerivedTemp : Base {};
+template <class T> class NonderivedTemp {};
+template <class T> class UndefinedTemp; // expected-note {{declared here}}
void is_base_of() {
int t01[T(__is_base_of(Base, Derived))];
@@ -486,7 +489,14 @@ void is_base_of() {
int t13[F(__is_base_of(Union, Union))];
int t14[T(__is_base_of(Empty, Empty))];
int t15[T(__is_base_of(class_forward, class_forward))];
- int t16[F(__is_base_of(Empty, class_forward))]; // expected-error {{incomplete type 'class_forward' used in type trait expression}}
+ int t16[F(__is_base_of(Empty, class_forward))]; // expected-error {{incomplete type 'class_forward' used in type trait expression}}
+ int t17[F(__is_base_of(Base&, Derived&))];
+ int t18[F(__is_base_of(Base[10], Derived[10]))];
+ int t19[F(__is_base_of(int, int))];
+ int t20[F(__is_base_of(long, int))];
+ int t21[T(__is_base_of(Base, DerivedTemp<int>))];
+ int t22[F(__is_base_of(Base, NonderivedTemp<int>))];
+ int t23[F(__is_base_of(Base, UndefinedTemp<int>))]; // expected-error {{implicit instantiation of undefined template 'UndefinedTemp<int>'}}
isBaseOfT<Base, Derived>();
isBaseOfF<Derived, Base>();