summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-11-20 22:03:38 +0000
committerDouglas Gregor <dgregor@apple.com>2009-11-20 22:03:38 +0000
commita25d65d1b6318407fb99a5de0a7720d8881146f3 (patch)
treec1cd754557864732dc71ac3b32546fd2db2abb69
parent09177b2b7fc0d08e55589cf8035ec9a54c4ce6c8 (diff)
downloadbcm5719-llvm-a25d65d1b6318407fb99a5de0a7720d8881146f3.tar.gz
bcm5719-llvm-a25d65d1b6318407fb99a5de0a7720d8881146f3.zip
Implement C++ [basic.lookup.classref]p3, which states how the type
name 'T' is looked up in the expression t.~T() Previously, we weren't looking into the type of "t", and therefore would fail when T actually referred to an injected-class-name. Fixes PR5530. llvm-svn: 89493
-rw-r--r--clang/include/clang/Parse/Action.h9
-rw-r--r--clang/lib/Parse/MinimalAction.cpp2
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp4
-rw-r--r--clang/lib/Sema/Sema.h3
-rw-r--r--clang/lib/Sema/SemaDecl.cpp81
-rw-r--r--clang/test/SemaCXX/pseudo-destructors.cpp9
6 files changed, 80 insertions, 28 deletions
diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h
index 45891bc0c98..018cc145403 100644
--- a/clang/include/clang/Parse/Action.h
+++ b/clang/include/clang/Parse/Action.h
@@ -203,11 +203,15 @@ public:
/// this occurs when deriving from "std::vector<T>::allocator_type", where T
/// is a template parameter.
///
+ /// \param ObjectType if we're checking whether an identifier is a type
+ /// within a C++ member access expression, this will be the type of the
+ ///
/// \returns the type referred to by this identifier, or NULL if the type
/// does not name an identifier.
virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, const CXXScopeSpec *SS = 0,
- bool isClassName = false) = 0;
+ bool isClassName = false,
+ TypeTy *ObjectType = 0) = 0;
/// isTagName() - This method is called *for error recovery purposes only*
/// to determine if the specified name is a valid tag name ("struct foo"). If
@@ -2518,7 +2522,8 @@ public:
/// does not name an identifier.
virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, const CXXScopeSpec *SS,
- bool isClassName = false);
+ bool isClassName = false,
+ TypeTy *ObjectType = 0);
/// isCurrentClassName - Always returns false, because MinimalAction
/// does not support C++ classes with constructors.
diff --git a/clang/lib/Parse/MinimalAction.cpp b/clang/lib/Parse/MinimalAction.cpp
index 7681eac6ed8..aa0b89b1a3a 100644
--- a/clang/lib/Parse/MinimalAction.cpp
+++ b/clang/lib/Parse/MinimalAction.cpp
@@ -144,7 +144,7 @@ void MinimalAction::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
Action::TypeTy *
MinimalAction::getTypeName(IdentifierInfo &II, SourceLocation Loc,
Scope *S, const CXXScopeSpec *SS,
- bool isClassName) {
+ bool isClassName, TypeTy *ObjectType) {
if (TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>())
if (TI->isTypeName)
return TI;
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index b2ecc9e827f..145c8616eb8 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1010,7 +1010,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
// Parse the type-specifier-seq.
DeclSpec DS;
- if (ParseCXXTypeSpecifierSeq(DS))
+ if (ParseCXXTypeSpecifierSeq(DS)) // FIXME: ObjectType?
return true;
// Parse the conversion-declarator, which is merely a sequence of
@@ -1152,7 +1152,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
// Note that this is a destructor name.
Action::TypeTy *Ty = Actions.getTypeName(*ClassName, ClassNameLoc,
- CurScope, &SS);
+ CurScope, &SS, false, ObjectType);
if (!Ty) {
if (ObjectType)
Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 72039e27569..6e74f9277a1 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -533,7 +533,8 @@ public:
virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, const CXXScopeSpec *SS,
- bool isClassName = false);
+ bool isClassName = false,
+ TypeTy *ObjectType = 0);
virtual DeclSpec::TST isTagName(IdentifierInfo &II, Scope *S);
virtual bool DiagnoseUnknownTypeName(const IdentifierInfo &II,
SourceLocation IILoc,
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index b5109f825e5..27c491c8820 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -66,31 +66,68 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(DeclPtrTy Ptr) {
/// and then return NULL.
Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, const CXXScopeSpec *SS,
- bool isClassName) {
- // C++ [temp.res]p3:
- // A qualified-id that refers to a type and in which the
- // nested-name-specifier depends on a template-parameter (14.6.2)
- // shall be prefixed by the keyword typename to indicate that the
- // qualified-id denotes a type, forming an
- // elaborated-type-specifier (7.1.5.3).
- //
- // We therefore do not perform any name lookup if the result would
- // refer to a member of an unknown specialization.
- if (SS && isUnknownSpecialization(*SS)) {
- if (!isClassName)
+ bool isClassName,
+ TypeTy *ObjectTypePtr) {
+ // Determine where we will perform name lookup.
+ DeclContext *LookupCtx = 0;
+ if (ObjectTypePtr) {
+ QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
+ if (ObjectType->isRecordType())
+ LookupCtx = computeDeclContext(ObjectType);
+ } else if (SS && SS->isSet()) {
+ LookupCtx = computeDeclContext(*SS, false);
+
+ if (!LookupCtx) {
+ if (isDependentScopeSpecifier(*SS)) {
+ // C++ [temp.res]p3:
+ // A qualified-id that refers to a type and in which the
+ // nested-name-specifier depends on a template-parameter (14.6.2)
+ // shall be prefixed by the keyword typename to indicate that the
+ // qualified-id denotes a type, forming an
+ // elaborated-type-specifier (7.1.5.3).
+ //
+ // We therefore do not perform any name lookup if the result would
+ // refer to a member of an unknown specialization.
+ if (!isClassName)
+ return 0;
+
+ // We know from the grammar that this name refers to a type, so build a
+ // TypenameType node to describe the type.
+ // FIXME: Record somewhere that this TypenameType node has no "typename"
+ // keyword associated with it.
+ return CheckTypenameType((NestedNameSpecifier *)SS->getScopeRep(),
+ II, SS->getRange()).getAsOpaquePtr();
+ }
+
+ return 0;
+ }
+
+ if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(*SS))
return 0;
-
- // We know from the grammar that this name refers to a type, so build a
- // TypenameType node to describe the type.
- // FIXME: Record somewhere that this TypenameType node has no "typename"
- // keyword associated with it.
- return CheckTypenameType((NestedNameSpecifier *)SS->getScopeRep(),
- II, SS->getRange()).getAsOpaquePtr();
}
-
+
LookupResult Result(*this, &II, NameLoc, LookupOrdinaryName);
- LookupParsedName(Result, S, SS, false);
-
+ if (LookupCtx) {
+ // Perform "qualified" name lookup into the declaration context we
+ // computed, which is either the type of the base of a member access
+ // expression or the declaration context associated with a prior
+ // nested-name-specifier.
+ LookupQualifiedName(Result, LookupCtx);
+
+ if (ObjectTypePtr && Result.empty()) {
+ // C++ [basic.lookup.classref]p3:
+ // If the unqualified-id is ~type-name, the type-name is looked up
+ // in the context of the entire postfix-expression. If the type T of
+ // the object expression is of a class type C, the type-name is also
+ // looked up in the scope of class C. At least one of the lookups shall
+ // find a name that refers to (possibly cv-qualified) T.
+ LookupName(Result, S);
+ }
+ } else {
+ // Perform unqualified name lookup.
+ LookupName(Result, S);
+ }
+
NamedDecl *IIDecl = 0;
switch (Result.getResultKind()) {
case LookupResult::NotFound:
diff --git a/clang/test/SemaCXX/pseudo-destructors.cpp b/clang/test/SemaCXX/pseudo-destructors.cpp
index 0850c44a36f..8f69def9fd4 100644
--- a/clang/test/SemaCXX/pseudo-destructors.cpp
+++ b/clang/test/SemaCXX/pseudo-destructors.cpp
@@ -38,3 +38,12 @@ typedef int Integer;
void destroy_without_call(int *ip) {
ip->~Integer; // expected-error{{called immediately}}
}
+
+// PR5530
+namespace N1 {
+ class X0 { };
+}
+
+void test_X0(N1::X0 &x0) {
+ x0.~X0();
+}
OpenPOWER on IntegriCloud