diff options
author | Douglas Gregor <dgregor@apple.com> | 2008-11-18 15:03:34 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2008-11-18 15:03:34 +0000 |
commit | 10c4262aeb5212375e3fa64e76887bd9bcc79924 (patch) | |
tree | ec0f8048581575e9882e5866b9ebce78b40ed4e9 | |
parent | e94ca9e4371c022329270436b3dd77adc4ddfa8f (diff) |
As threatened previously: consolidate name lookup and the creation of
DeclRefExprs and BlockDeclRefExprs into a single function
Sema::ActOnDeclarationNameExpr, eliminating a bunch of duplicate
lookup-name-and-check-the-result code.
Note that we still have the three parser entry points for identifiers,
operator-function-ids, and conversion-function-ids, since the parser
doesn't (and shouldn't) know about DeclarationNames. This is a Good
Thing (TM), and there will be more entrypoints coming (e.g., for C++
pseudo-destructor expressions).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59527 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticKinds.def | 5 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 6 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 49 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 71 | ||||
-rw-r--r-- | test/SemaCXX/conversion-function.cpp | 2 |
5 files changed, 49 insertions, 84 deletions
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 81f30e4540..5b2eb9a6d1 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -896,6 +896,8 @@ DIAG(err_unexpected_typedef_ident, ERROR, "unexpected type name '%0': expected identifier") DIAG(err_undeclared_var_use, ERROR, "use of undeclared identifier '%0'") +DIAG(err_undeclared_use, ERROR, + "use of undeclared '%0'") DIAG(warn_deprecated, WARNING, "'%0' is deprecated") DIAG(err_redefinition, ERROR, @@ -1379,9 +1381,6 @@ DIAG(warn_conv_to_base_not_used, WARNING, "be used") DIAG(warn_conv_to_void_not_used, WARNING, "conversion function converting '%0' to '%1' will never be used") -DIAG(err_no_conv_function, ERROR, - "no conversion function to type '%0'") - DIAG(warn_not_compound_assign, WARNING, "use of unary operator that may be intended as compound assignment (%0=)") diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 03099956b0..66c0138614 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -625,6 +625,12 @@ public: TypeTy *Ty, bool HasTrailingLParen, const CXXScopeSpec *SS); + ExprResult ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, + DeclarationName Name, + bool HasTrailingLParen, + const CXXScopeSpec *SS); + + virtual ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind); virtual ExprResult ActOnNumericConstant(const Token &); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index accdc32d45..6a98a5bc7e 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -347,19 +347,41 @@ Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc, IdentifierInfo &II, bool HasTrailingLParen, const CXXScopeSpec *SS) { + return ActOnDeclarationNameExpr(S, Loc, &II, HasTrailingLParen, SS); +} + +/// ActOnDeclarationNameExpr - The parser has read some kind of name +/// (e.g., a C++ id-expression (C++ [expr.prim]p1)). This routine +/// performs lookup on that name and returns an expression that refers +/// to that name. This routine isn't directly called from the parser, +/// because the parser doesn't know about DeclarationName. Rather, +/// this routine is called by ActOnIdentifierExpr, +/// ActOnOperatorFunctionIdExpr, and ActOnConversionFunctionExpr, +/// which form the DeclarationName from the corresponding syntactic +/// forms. +/// +/// HasTrailingLParen indicates whether this identifier is used in a +/// function call context. LookupCtx is only used for a C++ +/// qualified-id (foo::bar) to indicate the class or namespace that +/// the identifier must be a member of. +Sema::ExprResult Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, + DeclarationName Name, + bool HasTrailingLParen, + const CXXScopeSpec *SS) { // Could be enum-constant, value decl, instance variable, etc. Decl *D; if (SS && !SS->isEmpty()) { DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep()); if (DC == 0) return true; - D = LookupDecl(&II, Decl::IDNS_Ordinary, S, DC); + D = LookupDecl(Name, Decl::IDNS_Ordinary, S, DC); } else - D = LookupDecl(&II, Decl::IDNS_Ordinary, S); + D = LookupDecl(Name, Decl::IDNS_Ordinary, S); // If this reference is in an Objective-C method, then ivar lookup happens as // well. - if (getCurMethodDecl()) { + IdentifierInfo *II = Name.getAsIdentifierInfo(); + if (II && getCurMethodDecl()) { ScopedDecl *SD = dyn_cast_or_null<ScopedDecl>(D); // There are two cases to handle here. 1) scoped lookup could have failed, // in which case we should look for an ivar. 2) scoped lookup could have @@ -368,7 +390,7 @@ Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc, // name, if the lookup suceeds, we replace it our current decl. if (SD == 0 || SD->isDefinedOutsideFunctionOrMethod()) { ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); - if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(&II)) { + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II)) { // FIXME: This should use a new expr for a direct reference, don't turn // this into Self->ivar, just return a BareIVarExpr or something. IdentifierInfo &II = Context.Idents.get("self"); @@ -378,7 +400,7 @@ Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc, } } // Needed to implement property "super.method" notation. - if (SD == 0 && &II == SuperID) { + if (SD == 0 && II == SuperID) { QualType T = Context.getPointerType(Context.getObjCInterfaceType( getCurMethodDecl()->getClassInterface())); return new ObjCSuperExpr(Loc, T); @@ -387,17 +409,20 @@ Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc, if (D == 0) { // Otherwise, this could be an implicitly declared function reference (legal // in C90, extension in C99). - if (HasTrailingLParen && + if (HasTrailingLParen && II && !getLangOptions().CPlusPlus) // Not in C++. - D = ImplicitlyDefineFunction(Loc, II, S); + D = ImplicitlyDefineFunction(Loc, *II, S); else { // If this name wasn't predeclared and if this is not a function call, // diagnose the problem. if (SS && !SS->isEmpty()) return Diag(Loc, diag::err_typecheck_no_member, - II.getName(), SS->getRange()); + Name.getAsString(), SS->getRange()); + else if (Name.getNameKind() == DeclarationName::CXXOperatorName || + Name.getNameKind() == DeclarationName::CXXConversionFunctionName) + return Diag(Loc, diag::err_undeclared_use, Name.getAsString()); else - return Diag(Loc, diag::err_undeclared_var_use, II.getName()); + return Diag(Loc, diag::err_undeclared_var_use, Name.getAsString()); } } @@ -423,11 +448,11 @@ Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc, return Diag(Loc, diag::err_invalid_non_static_member_use, FD->getName()); } if (isa<TypedefDecl>(D)) - return Diag(Loc, diag::err_unexpected_typedef, II.getName()); + return Diag(Loc, diag::err_unexpected_typedef, Name.getAsString()); if (isa<ObjCInterfaceDecl>(D)) - return Diag(Loc, diag::err_unexpected_interface, II.getName()); + return Diag(Loc, diag::err_unexpected_interface, Name.getAsString()); if (isa<NamespaceDecl>(D)) - return Diag(Loc, diag::err_unexpected_namespace, II.getName()); + return Diag(Loc, diag::err_unexpected_namespace, Name.getAsString()); // Make the DeclRefExpr or BlockDeclRefExpr for the decl. if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index f2c6c3b35b..5864f222df 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -33,41 +33,8 @@ Sema::ExprResult Sema::ActOnConversionFunctionExpr(Scope *S, QualType ConvTypeCanon = Context.getCanonicalType(ConvType); DeclarationName ConvName = Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon); - - // We only expect to find a CXXConversionDecl. - Decl *D; - if (SS && !SS->isEmpty()) { - DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep()); - if (DC == 0) - return true; - D = LookupDecl(ConvName, Decl::IDNS_Ordinary, S, DC); - } else - D = LookupDecl(ConvName, Decl::IDNS_Ordinary, S); - - if (D == 0) { - // If there is no conversion function that converts to this type, - // diagnose the problem. - if (SS && !SS->isEmpty()) - return Diag(OperatorLoc, diag::err_typecheck_no_member, - ConvType.getAsString(), SS->getRange()); - else - return Diag(OperatorLoc, diag::err_no_conv_function, - ConvType.getAsString()); - } - - assert(isa<CXXConversionDecl>(D) && "we had to find a conversion function"); - CXXConversionDecl *Conversion = cast<CXXConversionDecl>(D); - - // check if referencing a declaration with __attribute__((deprecated)). - if (Conversion->getAttr<DeprecatedAttr>()) - Diag(OperatorLoc, diag::warn_deprecated, Conversion->getName()); - - // Only create DeclRefExpr's for valid Decl's. - if (Conversion->isInvalidDecl()) - return true; - - // Create a normal DeclRefExpr. - return new DeclRefExpr(Conversion, Conversion->getType(), OperatorLoc); + return ActOnDeclarationNameExpr(S, OperatorLoc, ConvName, HasTrailingLParen, + SS); } /// ActOnOperatorFunctionIdExpr - Parse a C++ overloaded operator @@ -81,39 +48,7 @@ Sema::ExprResult Sema::ActOnOperatorFunctionIdExpr(Scope *S, bool HasTrailingLParen, const CXXScopeSpec *SS) { DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(Op); - - Decl *D; - if (SS && !SS->isEmpty()) { - DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep()); - if (DC == 0) - return true; - D = LookupDecl(Name, Decl::IDNS_Ordinary, S, DC); - } else - D = LookupDecl(Name, Decl::IDNS_Ordinary, S); - - if (D == 0) { - // If there is no conversion function that converts to this type, - // diagnose the problem. - if (SS && !SS->isEmpty()) - return Diag(OperatorLoc, diag::err_typecheck_no_member, - Name.getAsString(), SS->getRange()); - else - return Diag(OperatorLoc, diag::err_undeclared_var_use, - Name.getAsString()); - } - - ValueDecl *VD = cast<ValueDecl>(D); - - // check if referencing a declaration with __attribute__((deprecated)). - if (VD->getAttr<DeprecatedAttr>()) - Diag(OperatorLoc, diag::warn_deprecated, Name.getAsString()); - - // Only create DeclRefExpr's for valid Decl's. - if (VD->isInvalidDecl()) - return true; - - // Create a normal DeclRefExpr. - return new DeclRefExpr(VD, VD->getType(), OperatorLoc); + return ActOnDeclarationNameExpr(S, OperatorLoc, Name, HasTrailingLParen, SS); } /// ActOnCXXTypeidOfType - Parse typeid( type-id ). diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp index 22ed411e64..3c2401f110 100644 --- a/test/SemaCXX/conversion-function.cpp +++ b/test/SemaCXX/conversion-function.cpp @@ -9,7 +9,7 @@ public: } float g() { - return operator float(); // expected-error{{no conversion function to type 'float'}} + return operator float(); // expected-error{{use of undeclared 'operator float'}} } }; |