[cfe-commits] r152137 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Driver/ include/clang/Frontend/ include/clang/Parse/ include/clang/Sema/ include/clang/Serialization/ lib/AST/ lib/CodeGen/ lib/Driver/ lib/Lex/ lib/Pars
Nico Weber
thakis at chromium.org
Wed Mar 14 10:42:44 PDT 2012
Hi Ted,
very cool!
I noticed everything except for the subscripting support works all the
way back on 10.5. Is that something that can be relied on? Can we use
array / dictionary / number literals on code that targets 10.5?
Thanks,
Nico
On Tue, Mar 6, 2012 at 12:05 PM, Ted Kremenek <kremenek at apple.com> wrote:
> Author: kremenek
> Date: Tue Mar 6 14:05:56 2012
> New Revision: 152137
>
> URL: http://llvm.org/viewvc/llvm-project?rev=152137&view=rev
> Log:
> Add clang support for new Objective-C literal syntax for NSDictionary, NSArray,
> NSNumber, and boolean literals. This includes both Sema and Codegen support.
> Included is also support for new Objective-C container subscripting.
>
> My apologies for the large patch. It was very difficult to break apart.
> The patch introduces changes to the driver as well to cause clang to link
> in additional runtime support when needed to support the new language features.
>
> Docs are forthcoming to document the implementation and behavior of these features.
>
> Added:
> cfe/trunk/include/clang/AST/NSAPI.h
> cfe/trunk/lib/AST/NSAPI.cpp
> cfe/trunk/test/CodeGenObjC/Inputs/
> cfe/trunk/test/CodeGenObjC/Inputs/literal-support.h
> cfe/trunk/test/CodeGenObjC/arc-literals.m
> cfe/trunk/test/CodeGenObjC/objc-arc-container-subscripting.m
> cfe/trunk/test/CodeGenObjC/objc-container-subscripting-1.m
> cfe/trunk/test/CodeGenObjC/objc-container-subscripting.m
> cfe/trunk/test/CodeGenObjC/objc-dictionary-literal.m
> cfe/trunk/test/CodeGenObjC/objc-literal-debugger-test.m
> cfe/trunk/test/CodeGenObjC/objc-literal-tests.m
> cfe/trunk/test/CodeGenObjC/optimized-setter.m
> cfe/trunk/test/CodeGenObjCXX/Inputs/
> cfe/trunk/test/CodeGenObjCXX/Inputs/literal-support.h
> cfe/trunk/test/CodeGenObjCXX/literals.mm
> cfe/trunk/test/CodeGenObjCXX/objc-container-subscripting-1.mm
> cfe/trunk/test/CodeGenObjCXX/objc-container-subscripting.mm
> cfe/trunk/test/Driver/arclite-link.c
> cfe/trunk/test/PCH/objc_container.h
> cfe/trunk/test/PCH/objc_container.m
> cfe/trunk/test/PCH/objc_literals.m
> cfe/trunk/test/PCH/objc_literals.mm
> cfe/trunk/test/PCH/subscripting-literals.m
> cfe/trunk/test/SemaObjC/cocoa-api-usage.m
> cfe/trunk/test/SemaObjC/cocoa-api-usage.m.fixed
> cfe/trunk/test/SemaObjC/objc-array-literal.m
> cfe/trunk/test/SemaObjC/objc-container-subscripting-1.m
> cfe/trunk/test/SemaObjC/objc-container-subscripting-2.m
> cfe/trunk/test/SemaObjC/objc-container-subscripting-3.m
> cfe/trunk/test/SemaObjC/objc-container-subscripting.m
> cfe/trunk/test/SemaObjC/objc-literal-nsnumber.m
> cfe/trunk/test/SemaObjC/objc-literal-sig.m
> cfe/trunk/test/SemaObjCXX/literals.mm
> cfe/trunk/test/SemaObjCXX/objc-container-subscripting.mm
> Modified:
> cfe/trunk/include/clang/AST/ASTContext.h
> cfe/trunk/include/clang/AST/ExprObjC.h
> cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> cfe/trunk/include/clang/AST/Stmt.h
> cfe/trunk/include/clang/Basic/DiagnosticGroups.td
> cfe/trunk/include/clang/Basic/DiagnosticIDs.h
> cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> cfe/trunk/include/clang/Basic/LangOptions.def
> cfe/trunk/include/clang/Basic/Specifiers.h
> cfe/trunk/include/clang/Basic/StmtNodes.td
> cfe/trunk/include/clang/Basic/TokenKinds.def
> cfe/trunk/include/clang/Driver/CC1Options.td
> cfe/trunk/include/clang/Driver/ObjCRuntime.h
> cfe/trunk/include/clang/Driver/Options.td
> cfe/trunk/include/clang/Frontend/PreprocessorOptions.h
> cfe/trunk/include/clang/Parse/Parser.h
> cfe/trunk/include/clang/Sema/Sema.h
> cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> cfe/trunk/lib/AST/ASTContext.cpp
> cfe/trunk/lib/AST/CMakeLists.txt
> cfe/trunk/lib/AST/Expr.cpp
> cfe/trunk/lib/AST/ExprClassification.cpp
> cfe/trunk/lib/AST/ExprConstant.cpp
> cfe/trunk/lib/AST/ItaniumMangle.cpp
> cfe/trunk/lib/AST/StmtDumper.cpp
> cfe/trunk/lib/AST/StmtPrinter.cpp
> cfe/trunk/lib/AST/StmtProfile.cpp
> cfe/trunk/lib/CodeGen/CGExprScalar.cpp
> cfe/trunk/lib/CodeGen/CGObjC.cpp
> cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
> cfe/trunk/lib/CodeGen/CGObjCMac.cpp
> cfe/trunk/lib/CodeGen/CGObjCRuntime.h
> cfe/trunk/lib/CodeGen/CodeGenFunction.h
> cfe/trunk/lib/Driver/ToolChains.cpp
> cfe/trunk/lib/Driver/ToolChains.h
> cfe/trunk/lib/Driver/Tools.cpp
> cfe/trunk/lib/Lex/PPMacroExpansion.cpp
> cfe/trunk/lib/Parse/ParseExpr.cpp
> cfe/trunk/lib/Parse/ParseObjc.cpp
> cfe/trunk/lib/Sema/Sema.cpp
> cfe/trunk/lib/Sema/SemaCast.cpp
> cfe/trunk/lib/Sema/SemaCodeComplete.cpp
> cfe/trunk/lib/Sema/SemaExpr.cpp
> cfe/trunk/lib/Sema/SemaExprCXX.cpp
> cfe/trunk/lib/Sema/SemaExprObjC.cpp
> cfe/trunk/lib/Sema/SemaPseudoObject.cpp
> cfe/trunk/lib/Sema/SemaStmt.cpp
> cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
> cfe/trunk/lib/Sema/TreeTransform.h
> cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
> cfe/trunk/lib/Serialization/ASTWriter.cpp
> cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
> cfe/trunk/test/Driver/darwin-ld.c
> cfe/trunk/test/Driver/rewrite-objc.m
> cfe/trunk/test/SemaObjC/invalid-code.m
> cfe/trunk/test/SemaObjC/sizeof-interface.m
>
> Modified: cfe/trunk/include/clang/AST/ASTContext.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/ASTContext.h (original)
> +++ cfe/trunk/include/clang/AST/ASTContext.h Tue Mar 6 14:05:56 2012
> @@ -564,6 +564,7 @@
> CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy;
> CanQualType PseudoObjectTy, ARCUnbridgedCastTy;
> CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
> + CanQualType ObjCBuiltinBoolTy;
>
> // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
> mutable QualType AutoDeductTy; // Deduction against 'auto'.
>
> Modified: cfe/trunk/include/clang/AST/ExprObjC.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprObjC.h?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/ExprObjC.h (original)
> +++ cfe/trunk/include/clang/AST/ExprObjC.h Tue Mar 6 14:05:56 2012
> @@ -18,6 +18,7 @@
> #include "clang/AST/Expr.h"
> #include "clang/AST/SelectorLocationsKind.h"
> #include "clang/Basic/IdentifierTable.h"
> +#include "clang/Sema/Ownership.h"
>
> namespace clang {
> class IdentifierInfo;
> @@ -56,6 +57,281 @@
> child_range children() { return child_range(&String, &String+1); }
> };
>
> +/// ObjCBoolLiteralExpr - Objective-C Boolean Literal.
> +///
> +class ObjCBoolLiteralExpr : public Expr {
> + bool Value;
> + SourceLocation Loc;
> +public:
> + ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
> + Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
> + false, false), Value(val), Loc(l) {}
> +
> + explicit ObjCBoolLiteralExpr(EmptyShell Empty)
> + : Expr(ObjCBoolLiteralExprClass, Empty) { }
> +
> + bool getValue() const { return Value; }
> + void setValue(bool V) { Value = V; }
> +
> + SourceRange getSourceRange() const { return SourceRange(Loc); }
> +
> + SourceLocation getLocation() const { return Loc; }
> + void setLocation(SourceLocation L) { Loc = L; }
> +
> + static bool classof(const Stmt *T) {
> + return T->getStmtClass() == ObjCBoolLiteralExprClass;
> + }
> + static bool classof(const ObjCBoolLiteralExpr *) { return true; }
> +
> + // Iterators
> + child_range children() { return child_range(); }
> +};
> +
> +/// ObjCNumericLiteral - used for objective-c numeric literals;
> +/// as in: @42 or @true (c++/objc++) or @__yes (c/objc)
> +class ObjCNumericLiteral : public Expr {
> + /// Number - expression AST node for the numeric literal
> + Stmt *Number;
> + ObjCMethodDecl *ObjCNumericLiteralMethod;
> + SourceLocation AtLoc;
> +public:
> + ObjCNumericLiteral(Stmt *NL, QualType T, ObjCMethodDecl *method,
> + SourceLocation L)
> + : Expr(ObjCNumericLiteralClass, T, VK_RValue, OK_Ordinary,
> + false, false, false, false), Number(NL),
> + ObjCNumericLiteralMethod(method), AtLoc(L) {}
> + explicit ObjCNumericLiteral(EmptyShell Empty)
> + : Expr(ObjCNumericLiteralClass, Empty) {}
> +
> + Expr *getNumber() { return cast<Expr>(Number); }
> + const Expr *getNumber() const { return cast<Expr>(Number); }
> +
> + ObjCMethodDecl *getObjCNumericLiteralMethod() const {
> + return ObjCNumericLiteralMethod;
> + }
> +
> + SourceLocation getAtLoc() const { return AtLoc; }
> +
> + SourceRange getSourceRange() const {
> + return SourceRange(AtLoc, Number->getSourceRange().getEnd());
> + }
> +
> + static bool classof(const Stmt *T) {
> + return T->getStmtClass() == ObjCNumericLiteralClass;
> + }
> + static bool classof(const ObjCNumericLiteral *) { return true; }
> +
> + // Iterators
> + child_range children() { return child_range(&Number, &Number+1); }
> +
> + friend class ASTStmtReader;
> +};
> +
> +/// ObjCArrayLiteral - used for objective-c array containers; as in:
> +/// @[@"Hello", NSApp, [NSNumber numberWithInt:42]];
> +class ObjCArrayLiteral : public Expr {
> + unsigned NumElements;
> + SourceRange Range;
> + ObjCMethodDecl *ArrayWithObjectsMethod;
> +
> + ObjCArrayLiteral(llvm::ArrayRef<Expr *> Elements,
> + QualType T, ObjCMethodDecl * Method,
> + SourceRange SR);
> +
> + explicit ObjCArrayLiteral(EmptyShell Empty, unsigned NumElements)
> + : Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {}
> +
> +public:
> + static ObjCArrayLiteral *Create(ASTContext &C,
> + llvm::ArrayRef<Expr *> Elements,
> + QualType T, ObjCMethodDecl * Method,
> + SourceRange SR);
> +
> + static ObjCArrayLiteral *CreateEmpty(ASTContext &C, unsigned NumElements);
> +
> + SourceRange getSourceRange() const { return Range; }
> +
> + static bool classof(const Stmt *T) {
> + return T->getStmtClass() == ObjCArrayLiteralClass;
> + }
> + static bool classof(const ObjCArrayLiteral *) { return true; }
> +
> + /// \brief Retrieve elements of array of literals.
> + Expr **getElements() { return reinterpret_cast<Expr **>(this + 1); }
> +
> + /// \brief Retrieve elements of array of literals.
> + const Expr * const *getElements() const {
> + return reinterpret_cast<const Expr * const*>(this + 1);
> + }
> +
> + /// getNumElements - Return number of elements of objective-c array literal.
> + unsigned getNumElements() const { return NumElements; }
> +
> + /// getExpr - Return the Expr at the specified index.
> + Expr *getElement(unsigned Index) {
> + assert((Index < NumElements) && "Arg access out of range!");
> + return cast<Expr>(getElements()[Index]);
> + }
> + const Expr *getElement(unsigned Index) const {
> + assert((Index < NumElements) && "Arg access out of range!");
> + return cast<Expr>(getElements()[Index]);
> + }
> +
> + ObjCMethodDecl *getArrayWithObjectsMethod() const {
> + return ArrayWithObjectsMethod;
> + }
> +
> + // Iterators
> + child_range children() {
> + return child_range((Stmt **)getElements(),
> + (Stmt **)getElements() + NumElements);
> + }
> +
> + friend class ASTStmtReader;
> +};
> +
> +/// \brief An element in an Objective-C dictionary literal.
> +///
> +struct ObjCDictionaryElement {
> + /// \brief The key for the dictionary element.
> + Expr *Key;
> +
> + /// \brief The value of the dictionary element.
> + Expr *Value;
> +
> + /// \brief The location of the ellipsis, if this is a pack expansion.
> + SourceLocation EllipsisLoc;
> +
> + /// \brief The number of elements this pack expansion will expand to, if
> + /// this is a pack expansion and is known.
> + llvm::Optional<unsigned> NumExpansions;
> +
> + /// \brief Determines whether this dictionary element is a pack expansion.
> + bool isPackExpansion() const { return EllipsisLoc.isValid(); }
> +};
> +
> +/// ObjCDictionaryLiteral - AST node to represent objective-c dictionary
> +/// literals; as in: @{@"name" : NSUserName(), @"date" : [NSDate date] };
> +class ObjCDictionaryLiteral : public Expr {
> + /// \brief Key/value pair used to store the key and value of a given element.
> + ///
> + /// Objects of this type are stored directly after the expression.
> + struct KeyValuePair {
> + Expr *Key;
> + Expr *Value;
> + };
> +
> + /// \brief Data that describes an element that is a pack expansion, used if any
> + /// of the elements in the dictionary literal are pack expansions.
> + struct ExpansionData {
> + /// \brief The location of the ellipsis, if this element is a pack
> + /// expansion.
> + SourceLocation EllipsisLoc;
> +
> + /// \brief If non-zero, the number of elements that this pack
> + /// expansion will expand to (+1).
> + unsigned NumExpansionsPlusOne;
> + };
> +
> + /// \brief The number of elements in this dictionary literal.
> + unsigned NumElements : 31;
> +
> + /// \brief Determine whether this dictionary literal has any pack expansions.
> + ///
> + /// If the dictionary literal has pack expansions, then there will
> + /// be an array of pack expansion data following the array of
> + /// key/value pairs, which provide the locations of the ellipses (if
> + /// any) and number of elements in the expansion (if known). If
> + /// there are no pack expansions, we optimize away this storage.
> + unsigned HasPackExpansions : 1;
> +
> + SourceRange Range;
> + ObjCMethodDecl *DictWithObjectsMethod;
> +
> + ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK,
> + bool HasPackExpansions,
> + QualType T, ObjCMethodDecl *method,
> + SourceRange SR);
> +
> + explicit ObjCDictionaryLiteral(EmptyShell Empty, unsigned NumElements,
> + bool HasPackExpansions)
> + : Expr(ObjCDictionaryLiteralClass, Empty), NumElements(NumElements),
> + HasPackExpansions(HasPackExpansions) {}
> +
> + KeyValuePair *getKeyValues() {
> + return reinterpret_cast<KeyValuePair *>(this + 1);
> + }
> +
> + const KeyValuePair *getKeyValues() const {
> + return reinterpret_cast<const KeyValuePair *>(this + 1);
> + }
> +
> + ExpansionData *getExpansionData() {
> + if (!HasPackExpansions)
> + return 0;
> +
> + return reinterpret_cast<ExpansionData *>(getKeyValues() + NumElements);
> + }
> +
> + const ExpansionData *getExpansionData() const {
> + if (!HasPackExpansions)
> + return 0;
> +
> + return reinterpret_cast<const ExpansionData *>(getKeyValues()+NumElements);
> + }
> +
> +public:
> + static ObjCDictionaryLiteral *Create(ASTContext &C,
> + ArrayRef<ObjCDictionaryElement> VK,
> + bool HasPackExpansions,
> + QualType T, ObjCMethodDecl *method,
> + SourceRange SR);
> +
> + static ObjCDictionaryLiteral *CreateEmpty(ASTContext &C,
> + unsigned NumElements,
> + bool HasPackExpansions);
> +
> + /// getNumElements - Return number of elements of objective-c dictionary
> + /// literal.
> + unsigned getNumElements() const { return NumElements; }
> +
> + ObjCDictionaryElement getKeyValueElement(unsigned Index) const {
> + assert((Index < NumElements) && "Arg access out of range!");
> + const KeyValuePair &KV = getKeyValues()[Index];
> + ObjCDictionaryElement Result = { KV.Key, KV.Value, SourceLocation(),
> + llvm::Optional<unsigned>() };
> + if (HasPackExpansions) {
> + const ExpansionData &Expansion = getExpansionData()[Index];
> + Result.EllipsisLoc = Expansion.EllipsisLoc;
> + if (Expansion.NumExpansionsPlusOne > 0)
> + Result.NumExpansions = Expansion.NumExpansionsPlusOne - 1;
> + }
> + return Result;
> + }
> +
> + ObjCMethodDecl *getDictWithObjectsMethod() const
> + { return DictWithObjectsMethod; }
> +
> + SourceRange getSourceRange() const { return Range; }
> +
> + static bool classof(const Stmt *T) {
> + return T->getStmtClass() == ObjCDictionaryLiteralClass;
> + }
> + static bool classof(const ObjCDictionaryLiteral *) { return true; }
> +
> + // Iterators
> + child_range children() {
> + // Note: we're taking advantage of the layout of the KeyValuePair struct
> + // here. If that struct changes, this code will need to change as well.
> + return child_range(reinterpret_cast<Stmt **>(this + 1),
> + reinterpret_cast<Stmt **>(this + 1) + NumElements * 2);
> + }
> +
> + friend class ASTStmtReader;
> + friend class ASTStmtWriter;
> +};
> +
> +
> /// ObjCEncodeExpr, used for @encode in Objective-C. @encode has the same type
> /// and behavior as StringLiteral except that the string initializer is obtained
> /// from ASTContext with the encoding type as an argument.
> @@ -430,6 +706,88 @@
> void setLocation(SourceLocation L) { IdLoc = L; }
> void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; }
> };
> +
> +/// ObjCSubscriptRefExpr - used for array and dictionary subscripting.
> +/// array[4] = array[3]; dictionary[key] = dictionary[alt_key];
> +///
> +class ObjCSubscriptRefExpr : public Expr {
> + // Location of ']' in an indexing expression.
> + SourceLocation RBracket;
> + // array/dictionary base expression.
> + // for arrays, this is a numeric expression. For dictionaries, this is
> + // an objective-c object pointer expression.
> + enum { BASE, KEY, END_EXPR };
> + Stmt* SubExprs[END_EXPR];
> +
> + ObjCMethodDecl *GetAtIndexMethodDecl;
> +
> + // For immutable objects this is null. When ObjCSubscriptRefExpr is to read
> + // an indexed object this is null too.
> + ObjCMethodDecl *SetAtIndexMethodDecl;
> +
> +public:
> +
> + ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T,
> + ExprValueKind VK, ExprObjectKind OK,
> + ObjCMethodDecl *getMethod,
> + ObjCMethodDecl *setMethod, SourceLocation RB)
> + : Expr(ObjCSubscriptRefExprClass, T, VK, OK,
> + base->isTypeDependent() || key->isTypeDependent(),
> + base->isValueDependent() || key->isValueDependent(),
> + base->isInstantiationDependent() || key->isInstantiationDependent(),
> + (base->containsUnexpandedParameterPack() ||
> + key->containsUnexpandedParameterPack())),
> + RBracket(RB),
> + GetAtIndexMethodDecl(getMethod),
> + SetAtIndexMethodDecl(setMethod)
> + {SubExprs[BASE] = base; SubExprs[KEY] = key;}
> +
> + explicit ObjCSubscriptRefExpr(EmptyShell Empty)
> + : Expr(ObjCSubscriptRefExprClass, Empty) {}
> +
> + static ObjCSubscriptRefExpr *Create(ASTContext &C,
> + Expr *base,
> + Expr *key, QualType T,
> + ObjCMethodDecl *getMethod,
> + ObjCMethodDecl *setMethod,
> + SourceLocation RB);
> +
> + SourceLocation getRBracket() const { return RBracket; }
> + void setRBracket(SourceLocation RB) { RBracket = RB; }
> + SourceRange getSourceRange() const {
> + return SourceRange(SubExprs[BASE]->getLocStart(), RBracket);
> + }
> +
> + static bool classof(const Stmt *T) {
> + return T->getStmtClass() == ObjCSubscriptRefExprClass;
> + }
> + static bool classof(const ObjCSubscriptRefExpr *) { return true; }
> +
> + Expr *getBaseExpr() const { return cast<Expr>(SubExprs[BASE]); }
> + void setBaseExpr(Stmt *S) { SubExprs[BASE] = S; }
> +
> + Expr *getKeyExpr() const { return cast<Expr>(SubExprs[KEY]); }
> + void setKeyExpr(Stmt *S) { SubExprs[KEY] = S; }
> +
> + ObjCMethodDecl *getAtIndexMethodDecl() const {
> + return GetAtIndexMethodDecl;
> + }
> +
> + ObjCMethodDecl *setAtIndexMethodDecl() const {
> + return SetAtIndexMethodDecl;
> + }
> +
> + bool isArraySubscriptRefExpr() const {
> + return getKeyExpr()->getType()->isIntegralOrEnumerationType();
> + }
> +
> + child_range children() {
> + return child_range(SubExprs, SubExprs+END_EXPR);
> + }
> +private:
> + friend class ASTStmtReader;
> +};
> +
>
> /// \brief An expression that sends a message to the given Objective-C
> /// object or class.
>
> Added: cfe/trunk/include/clang/AST/NSAPI.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/NSAPI.h?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/include/clang/AST/NSAPI.h (added)
> +++ cfe/trunk/include/clang/AST/NSAPI.h Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,151 @@
> +//===--- NSAPI.h - NSFoundation APIs ----------------------------*- C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_CLANG_AST_NSAPI_H
> +#define LLVM_CLANG_AST_NSAPI_H
> +
> +#include "clang/Basic/IdentifierTable.h"
> +#include "llvm/ADT/Optional.h"
> +
> +namespace clang {
> + class ASTContext;
> + class QualType;
> +
> +// \brief Provides info and caches identifiers/selectors for NSFoundation API.
> +class NSAPI {
> +public:
> + explicit NSAPI(ASTContext &Ctx);
> +
> + ASTContext &getASTContext() const { return Ctx; }
> +
> + enum NSClassIdKindKind {
> + ClassId_NSString,
> + ClassId_NSArray,
> + ClassId_NSMutableArray,
> + ClassId_NSDictionary,
> + ClassId_NSMutableDictionary,
> + ClassId_NSNumber
> + };
> + static const unsigned NumClassIds = 6;
> +
> + enum NSStringMethodKind {
> + NSStr_stringWithString,
> + NSStr_initWithString
> + };
> + static const unsigned NumNSStringMethods = 2;
> +
> + IdentifierInfo *getNSClassId(NSClassIdKindKind K) const;
> +
> + /// \brief The Objective-C NSString selectors.
> + Selector getNSStringSelector(NSStringMethodKind MK) const;
> +
> + /// \brief Enumerates the NSArray methods used to generate literals.
> + enum NSArrayMethodKind {
> + NSArr_array,
> + NSArr_arrayWithArray,
> + NSArr_arrayWithObject,
> + NSArr_arrayWithObjects,
> + NSArr_arrayWithObjectsCount,
> + NSArr_initWithArray,
> + NSArr_initWithObjects,
> + NSArr_objectAtIndex,
> + NSMutableArr_replaceObjectAtIndex
> + };
> + static const unsigned NumNSArrayMethods = 9;
> +
> + /// \brief The Objective-C NSArray selectors.
> + Selector getNSArraySelector(NSArrayMethodKind MK) const;
> +
> + /// \brief Return NSArrayMethodKind if \arg Sel is such a selector.
> + llvm::Optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel);
> +
> + /// \brief Enumerates the NSDictionary methods used to generate literals.
> + enum NSDictionaryMethodKind {
> + NSDict_dictionary,
> + NSDict_dictionaryWithDictionary,
> + NSDict_dictionaryWithObjectForKey,
> + NSDict_dictionaryWithObjectsForKeys,
> + NSDict_dictionaryWithObjectsForKeysCount,
> + NSDict_dictionaryWithObjectsAndKeys,
> + NSDict_initWithDictionary,
> + NSDict_initWithObjectsAndKeys,
> + NSDict_objectForKey,
> + NSMutableDict_setObjectForKey
> + };
> + static const unsigned NumNSDictionaryMethods = 10;
> +
> + /// \brief The Objective-C NSDictionary selectors.
> + Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const;
> +
> + /// \brief Return NSDictionaryMethodKind if \arg Sel is such a selector.
> + llvm::Optional<NSDictionaryMethodKind>
> + getNSDictionaryMethodKind(Selector Sel);
> +
> + /// \brief Enumerates the NSNumber methods used to generate literals.
> + enum NSNumberLiteralMethodKind {
> + NSNumberWithChar,
> + NSNumberWithUnsignedChar,
> + NSNumberWithShort,
> + NSNumberWithUnsignedShort,
> + NSNumberWithInt,
> + NSNumberWithUnsignedInt,
> + NSNumberWithLong,
> + NSNumberWithUnsignedLong,
> + NSNumberWithLongLong,
> + NSNumberWithUnsignedLongLong,
> + NSNumberWithFloat,
> + NSNumberWithDouble,
> + NSNumberWithBool,
> + NSNumberWithInteger,
> + NSNumberWithUnsignedInteger
> + };
> + static const unsigned NumNSNumberLiteralMethods = 15;
> +
> + /// \brief The Objective-C NSNumber selectors used to create NSNumber literals.
> + /// \param Instance if true it will return the selector for the init* method
> + /// otherwise it will return the selector for the number* method.
> + Selector getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
> + bool Instance) const;
> +
> + bool isNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
> + Selector Sel) const {
> + return Sel == getNSNumberLiteralSelector(MK, false) ||
> + Sel == getNSNumberLiteralSelector(MK, true);
> + }
> +
> + /// \brief Return NSNumberLiteralMethodKind if \arg Sel is such a selector.
> + llvm::Optional<NSNumberLiteralMethodKind>
> + getNSNumberLiteralMethodKind(Selector Sel) const;
> +
> + /// \brief Determine the appropriate NSNumber factory method kind for a
> + /// literal of the given type.
> + static llvm::Optional<NSNumberLiteralMethodKind>
> + getNSNumberFactoryMethodKind(QualType T);
> +
> +private:
> + ASTContext &Ctx;
> +
> + mutable IdentifierInfo *ClassIds[NumClassIds];
> +
> + mutable Selector NSStringSelectors[NumNSStringMethods];
> +
> + /// \brief The selectors for Objective-C NSArray methods.
> + mutable Selector NSArraySelectors[NumNSArrayMethods];
> +
> + /// \brief The selectors for Objective-C NSDictionary methods.
> + mutable Selector NSDictionarySelectors[NumNSDictionaryMethods];
> +
> + /// \brief The Objective-C NSNumber selectors used to create NSNumber literals.
> + mutable Selector NSNumberClassSelectors[NumNSNumberLiteralMethods];
> + mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods];
> +};
> +
> +} // end namespace clang
> +
> +#endif // LLVM_CLANG_AST_NSAPI_H
>
> Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
> +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Mar 6 14:05:56 2012
> @@ -2041,11 +2041,13 @@
> DEF_TRAVERSE_STMT(ExtVectorElementExpr, { })
> DEF_TRAVERSE_STMT(GNUNullExpr, { })
> DEF_TRAVERSE_STMT(ImplicitValueInitExpr, { })
> +DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, { })
> DEF_TRAVERSE_STMT(ObjCEncodeExpr, { })
> DEF_TRAVERSE_STMT(ObjCIsaExpr, { })
> DEF_TRAVERSE_STMT(ObjCIvarRefExpr, { })
> DEF_TRAVERSE_STMT(ObjCMessageExpr, { })
> DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { })
> +DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, { })
> DEF_TRAVERSE_STMT(ObjCProtocolExpr, { })
> DEF_TRAVERSE_STMT(ObjCSelectorExpr, { })
> DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, { })
> @@ -2103,7 +2105,10 @@
> DEF_TRAVERSE_STMT(ImaginaryLiteral, { })
> DEF_TRAVERSE_STMT(StringLiteral, { })
> DEF_TRAVERSE_STMT(ObjCStringLiteral, { })
> -
> +DEF_TRAVERSE_STMT(ObjCNumericLiteral, { })
> +DEF_TRAVERSE_STMT(ObjCArrayLiteral, { })
> +DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, { })
> +
> // Traverse OpenCL: AsType, Convert.
> DEF_TRAVERSE_STMT(AsTypeExpr, { })
>
>
> Modified: cfe/trunk/include/clang/AST/Stmt.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Stmt.h (original)
> +++ cfe/trunk/include/clang/AST/Stmt.h Tue Mar 6 14:05:56 2012
> @@ -141,6 +141,8 @@
> friend class CallExpr; // ctor
> friend class OffsetOfExpr; // ctor
> friend class ObjCMessageExpr; // ctor
> + friend class ObjCArrayLiteral; // ctor
> + friend class ObjCDictionaryLiteral; // ctor
> friend class ShuffleVectorExpr; // ctor
> friend class ParenListExpr; // ctor
> friend class CXXUnresolvedConstructExpr; // ctor
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Tue Mar 6 14:05:56 2012
> @@ -379,3 +379,13 @@
> def ObjCNonUnifiedException : DiagGroup<"objc-nonunified-exceptions">;
>
> def ObjCProtocolMethodImpl : DiagGroup<"objc-protocol-method-implementation">;
> +
> +// ObjC API warning groups.
> +def ObjCRedundantLiteralUse : DiagGroup<"objc-redundant-literal-use">;
> +def ObjCRedundantAPIUse : DiagGroup<"objc-redundant-api-use", [
> + ObjCRedundantLiteralUse
> + ]>;
> +
> +def ObjCCocoaAPI : DiagGroup<"objc-cocoa-api", [
> + ObjCRedundantAPIUse
> + ]>;
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticIDs.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticIDs.h?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticIDs.h (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticIDs.h Tue Mar 6 14:05:56 2012
> @@ -36,7 +36,7 @@
> DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + 100,
> DIAG_START_LEX = DIAG_START_SERIALIZATION + 120,
> DIAG_START_PARSE = DIAG_START_LEX + 300,
> - DIAG_START_AST = DIAG_START_PARSE + 350,
> + DIAG_START_AST = DIAG_START_PARSE + 400,
> DIAG_START_SEMA = DIAG_START_AST + 100,
> DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000,
> DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Tue Mar 6 14:05:56 2012
> @@ -331,6 +331,8 @@
> def err_objc_unknown_at : Error<"expected an Objective-C directive after '@'">;
> def err_illegal_super_cast : Error<
> "cannot cast 'super' (it isn't an expression)">;
> +def err_nsnumber_nonliteral_unary : Error<
> + "@%0 must be followed by a number to form an NSNumber object">;
>
> let CategoryName = "ARC Parse Issue" in {
> def err_arc_bridge_retain : Error<
> @@ -410,6 +412,8 @@
> InGroup<CXX98Compat>, DefaultIgnore;
> def err_expected_catch : Error<"expected catch">;
> def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
> +def err_expected_rbrace_or_comma : Error<"expected '}' or ','">;
> +def err_expected_rsquare_or_comma : Error<"expected ']' or ','">;
> def err_using_namespace_in_class : Error<
> "'using namespace' is not allowed in classes">;
> def err_destructor_tilde_identifier : Error<
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Mar 6 14:05:56 2012
> @@ -542,6 +542,7 @@
> "multiple methods named %0 found">, InGroup<StrictSelector>, DefaultIgnore;
> def warn_accessor_property_type_mismatch : Warning<
> "type of property %0 does not match type of accessor %1">;
> +def not_conv_function_declared_at : Note<"type conversion function declared here">;
> def note_method_declared_at : Note<"method %0 declared here">;
> def err_setter_type_void : Error<"type of setter must be void">;
> def err_duplicate_method_decl : Error<"duplicate declaration of method %0">;
> @@ -1484,6 +1485,39 @@
> "the type %0 is already explicitly ownership-qualified">;
> def err_attribute_not_string : Error<
> "argument to %0 attribute was not a string literal">;
> +def err_undeclared_nsnumber : Error<
> + "NSNumber must be available to use Objective-C literals">;
> +def err_invalid_nsnumber_type : Error<
> + "%0 is not a valid literal type for NSNumber">;
> +def err_undeclared_nsarray : Error<
> + "NSArray must be available to use Objective-C array literals">;
> +def err_undeclared_nsdictionary : Error<
> + "NSDictionary must be available to use Objective-C dictionary "
> + "literals">;
> +def err_undeclared_arraywithobjects : Error<
> + "declaration of %0 is missing in NSArray class">;
> +def err_undeclared_dictwithobjects : Error<
> + "declaration of %0 is missing in NSDictionary class">;
> +def err_undeclared_nsnumber_method : Error<
> + "declaration of %0 is missing in NSNumber class">;
> +def err_objc_literal_method_sig : Error<
> + "literal construction method %0 has incompatible signature">;
> +def note_objc_literal_method_param : Note<
> + "%select{first|second|third}0 parameter has unexpected type %1 "
> + "(should be %2)">;
> +def note_objc_literal_method_return : Note<
> + "method returns unexpected type %0 (should be an object type)">;
> +def err_invalid_collection_element : Error<
> + "collection element of type %0 is not an Objective-C object">;
> +def err_box_literal_collection : Error<
> + "%select{string|character|boolean|numeric}0 literal must be prefixed by '@' "
> + "in a collection">;
> +
> +let CategoryName = "Cocoa API Issue" in {
> +def warn_objc_redundant_literal_use : Warning<
> + "using %0 with a literal is redundant">, InGroup<ObjCRedundantLiteralUse>;
> +}
> +
> def err_only_annotate_after_access_spec : Error<
> "access specifier can only have annotation attributes">;
> def err_attribute_section_invalid_for_target : Error<
> @@ -2642,6 +2676,8 @@
> def note_template_declared_here : Note<
> "%select{function template|class template|type alias template|template template parameter}0 "
> "%1 declared here">;
> +def note_parameter_type : Note<
> + "parameter of type %0 is declared here">;
>
> // C++11 Variadic Templates
> def err_template_param_pack_default_arg : Error<
> @@ -3709,6 +3745,33 @@
> "%0 is not a valid property name (accessing an object of type %1)">;
> def err_getter_not_found : Error<
> "expected getter method not found on object of type %0">;
> +def err_objc_subscript_method_not_found : Error<
> + "expected method to %select{read|write}1 %select{dictionary|array}2 element not "
> + "found on object of type %0">;
> +def err_objc_subscript_index_type : Error<
> + "method index parameter type %0 is not integral type">;
> +def err_objc_subscript_key_type : Error<
> + "method key parameter type %0 is not object type">;
> +def err_objc_subscript_dic_object_type : Error<
> + "method object parameter type %0 is not object type">;
> +def err_objc_subscript_object_type : Error<
> + "cannot assign to this %select{dictionary|array}1 because assigning method's 2nd parameter"
> + " of type %0 is not an objective-C pointer type">;
> +def err_objc_subscript_base_type : Error<
> + "%select{dictionary|array}1 subscript base type %0 is not an Objective-C object">;
> +def err_objc_multiple_subscript_type_conversion : Error<
> + "indexing expression is invalid because subscript type %0 has "
> + "multiple type conversion functions">;
> +def err_objc_subscript_type_conversion : Error<
> + "indexing expression is invalid because subscript type %0 is not an intergal"
> + "or objective-C pointer type">;
> +def err_objc_indexing_method_result_type : Error<
> + "method for accessing %select{dictionary|array}1 element must have Objective-C"
> + " object return type instead of %0">;
> +def err_objc_index_incomplete_class_type : Error<
> + "objective-C index expression has incomplete class type %0">;
> +def err_illegal_container_subscripting_op : Error<
> + "illegal operation on objective-c container subscripting">;
> def err_property_not_found_forward_class : Error<
> "property %0 cannot be found in forward class object %1">;
> def err_property_not_as_forward_class : Error<
> @@ -4438,6 +4501,9 @@
> def warn_unused_property_expr : Warning<
> "property access result unused - getters should not be used for side effects">,
> InGroup<UnusedValue>;
> +def warn_unused_container_subscript_expr : Warning<
> + "container access result unused - container access should not be used for side effects">,
> + InGroup<UnusedValue>;
> def warn_unused_call : Warning<
> "ignoring return value of function declared with %0 attribute">,
> InGroup<UnusedValue>;
>
> Modified: cfe/trunk/include/clang/Basic/LangOptions.def
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.def?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/LangOptions.def (original)
> +++ cfe/trunk/include/clang/Basic/LangOptions.def Tue Mar 6 14:05:56 2012
> @@ -124,6 +124,7 @@
> BENIGN_LANGOPT(ParseUnknownAnytype, 1, 0, "__unknown_anytype")
> BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support")
> BENIGN_LANGOPT(DebuggerCastResultToId, 1, 0, "for 'po' in the debugger, cast the result to id if it is of unknown type")
> +BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger objective-C literals and subscripting support")
> BENIGN_LANGOPT(AddressSanitizer , 1, 0, "AddressSanitizer enabled")
> BENIGN_LANGOPT(ThreadSanitizer , 1, 0, "ThreadSanitizer enabled")
>
>
> Modified: cfe/trunk/include/clang/Basic/Specifiers.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Specifiers.h?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/Specifiers.h (original)
> +++ cfe/trunk/include/clang/Basic/Specifiers.h Tue Mar 6 14:05:56 2012
> @@ -113,7 +113,12 @@
>
> /// An Objective C property is a logical field of an Objective-C
> /// object which is read and written via Objective C method calls.
> - OK_ObjCProperty
> + OK_ObjCProperty,
> +
> + /// An Objective C array/dictionary subscripting which reads an object
> + /// or writes at the subscripted array/dictionary element via
> + /// Objective C method calls.
> + OK_ObjCSubscript
> };
>
> // \brief Describes the kind of template specialization that a
>
> Modified: cfe/trunk/include/clang/Basic/StmtNodes.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/StmtNodes.td (original)
> +++ cfe/trunk/include/clang/Basic/StmtNodes.td Tue Mar 6 14:05:56 2012
> @@ -132,6 +132,9 @@
>
> // Obj-C Expressions.
> def ObjCStringLiteral : DStmt<Expr>;
> +def ObjCNumericLiteral : DStmt<Expr>;
> +def ObjCArrayLiteral : DStmt<Expr>;
> +def ObjCDictionaryLiteral : DStmt<Expr>;
> def ObjCEncodeExpr : DStmt<Expr>;
> def ObjCMessageExpr : DStmt<Expr>;
> def ObjCSelectorExpr : DStmt<Expr>;
> @@ -140,6 +143,8 @@
> def ObjCPropertyRefExpr : DStmt<Expr>;
> def ObjCIsaExpr : DStmt<Expr>;
> def ObjCIndirectCopyRestoreExpr : DStmt<Expr>;
> +def ObjCBoolLiteralExpr : DStmt<Expr>;
> +def ObjCSubscriptRefExpr : DStmt<Expr>;
>
> // Obj-C ARC Expressions.
> def ObjCBridgedCastExpr : DStmt<ExplicitCastExpr>;
>
> Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
> +++ cfe/trunk/include/clang/Basic/TokenKinds.def Tue Mar 6 14:05:56 2012
> @@ -258,6 +258,9 @@
> KEYWORD(_Imaginary , KEYALL)
> KEYWORD(_Static_assert , KEYALL)
> KEYWORD(__func__ , KEYALL)
> +KEYWORD(__objc_yes , KEYALL)
> +KEYWORD(__objc_no , KEYALL)
> +
>
> // C++ 2.11p1: Keywords.
> KEYWORD(asm , KEYCXX|KEYGNU)
>
> Modified: cfe/trunk/include/clang/Driver/CC1Options.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Driver/CC1Options.td (original)
> +++ cfe/trunk/include/clang/Driver/CC1Options.td Tue Mar 6 14:05:56 2012
> @@ -661,6 +661,8 @@
> HelpText<"Enable special debugger support behavior">;
> def fdebugger_cast_result_to_id : Flag<"-fdebugger-cast-result-to-id">,
> HelpText<"Enable casting unknown expression results to id">;
> +def fdebugger_objc_literal : Flag<"-fdebugger-objc-literal">,
> + HelpText<"Enable special debugger support for objective-C subscripting and literals">;
> def fdeprecated_macro : Flag<"-fdeprecated-macro">,
> HelpText<"Defines the __DEPRECATED macro">;
> def fno_deprecated_macro : Flag<"-fno-deprecated-macro">,
>
> Modified: cfe/trunk/include/clang/Driver/ObjCRuntime.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/ObjCRuntime.h?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Driver/ObjCRuntime.h (original)
> +++ cfe/trunk/include/clang/Driver/ObjCRuntime.h Tue Mar 6 14:05:56 2012
> @@ -30,6 +30,9 @@
> /// True if the runtime supports ARC zeroing __weak.
> unsigned HasWeak : 1;
>
> + /// \brief True if the runtime supports subscripting methods.
> + unsigned HasSubscripting : 1;
> +
> /// True if the runtime provides the following entrypoint:
> /// void objc_terminate(void);
> /// If available, this will be called instead of abort() when an
> @@ -37,7 +40,7 @@
> unsigned HasTerminate : 1;
>
> ObjCRuntime() : RuntimeKind(NeXT), HasARC(false), HasWeak(false),
> - HasTerminate(false) {}
> + HasSubscripting(false), HasTerminate(false) {}
> };
>
> }
>
> Modified: cfe/trunk/include/clang/Driver/Options.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Driver/Options.td (original)
> +++ cfe/trunk/include/clang/Driver/Options.td Tue Mar 6 14:05:56 2012
> @@ -463,6 +463,7 @@
> Group<f_Group>;
> def fno_objc_infer_related_result_type : Flag<
> "-fno-objc-infer-related-result-type">, Group<f_Group>;
> +def fobjc_link_runtime: Flag<"-fobjc-link-runtime">, Group<f_Group>;
>
> // Objective-C ABI options.
> def fobjc_abi_version_EQ : Joined<"-fobjc-abi-version=">, Group<f_Group>;
>
> Modified: cfe/trunk/include/clang/Frontend/PreprocessorOptions.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PreprocessorOptions.h?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Frontend/PreprocessorOptions.h (original)
> +++ cfe/trunk/include/clang/Frontend/PreprocessorOptions.h Tue Mar 6 14:05:56 2012
> @@ -10,6 +10,7 @@
> #ifndef LLVM_CLANG_FRONTEND_PREPROCESSOROPTIONS_H_
> #define LLVM_CLANG_FRONTEND_PREPROCESSOROPTIONS_H_
>
> +#include "llvm/ADT/SmallVector.h"
> #include "llvm/ADT/StringRef.h"
> #include <cassert>
> #include <string>
>
> Modified: cfe/trunk/include/clang/Parse/Parser.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Parse/Parser.h (original)
> +++ cfe/trunk/include/clang/Parse/Parser.h Tue Mar 6 14:05:56 2012
> @@ -1362,6 +1362,8 @@
> ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral = false);
>
> ExprResult ParseGenericSelectionExpression();
> +
> + ExprResult ParseObjCBoolLiteral();
>
> //===--------------------------------------------------------------------===//
> // C++ Expressions
> @@ -1490,6 +1492,11 @@
> // Objective-C Expressions
> ExprResult ParseObjCAtExpression(SourceLocation AtLocation);
> ExprResult ParseObjCStringLiteral(SourceLocation AtLoc);
> + ExprResult ParseObjCCharacterLiteral(SourceLocation AtLoc);
> + ExprResult ParseObjCNumericLiteral(SourceLocation AtLoc);
> + ExprResult ParseObjCBooleanLiteral(SourceLocation AtLoc, bool ArgValue);
> + ExprResult ParseObjCArrayLiteral(SourceLocation AtLoc);
> + ExprResult ParseObjCDictionaryLiteral(SourceLocation AtLoc);
> ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc);
> ExprResult ParseObjCSelectorExpression(SourceLocation AtLoc);
> ExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);
> @@ -1503,7 +1510,7 @@
> SourceLocation LBracloc, SourceLocation SuperLoc,
> ParsedType ReceiverType, ExprArg ReceiverExpr);
> bool ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr);
> -
> +
> //===--------------------------------------------------------------------===//
> // C99 6.8: Statements and Blocks.
>
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Tue Mar 6 14:05:56 2012
> @@ -25,9 +25,11 @@
> #include "clang/Sema/TypoCorrection.h"
> #include "clang/Sema/Weak.h"
> #include "clang/AST/Expr.h"
> +#include "clang/AST/ExprObjC.h"
> #include "clang/AST/DeclarationName.h"
> #include "clang/AST/ExternalASTSource.h"
> #include "clang/AST/TypeLoc.h"
> +#include "clang/AST/NSAPI.h"
> #include "clang/Lex/ModuleLoader.h"
> #include "clang/Basic/Specifiers.h"
> #include "clang/Basic/TemplateKinds.h"
> @@ -511,11 +513,34 @@
> /// \brief The MSVC "_GUID" struct, which is defined in MSVC header files.
> RecordDecl *MSVCGuidDecl;
>
> + /// \brief Caches identifiers/selectors for NSFoundation APIs.
> + llvm::OwningPtr<NSAPI> NSAPIObj;
> +
> + /// \brief The declaration of the Objective-C NSNumber class.
> + ObjCInterfaceDecl *NSNumberDecl;
> +
> + /// \brief The Objective-C NSNumber methods used to create NSNumber literals.
> + ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods];
> +
> + /// \brief The declaration of the Objective-C NSArray class.
> + ObjCInterfaceDecl *NSArrayDecl;
> +
> + /// \brief The declaration of the arrayWithObjects:count: method.
> + ObjCMethodDecl *ArrayWithObjectsMethod;
> +
> + /// \brief The declaration of the Objective-C NSDictionary class.
> + ObjCInterfaceDecl *NSDictionaryDecl;
> +
> + /// \brief The declaration of the dictionaryWithObjects:forKeys:count: method.
> + ObjCMethodDecl *DictionaryWithObjectsMethod;
> +
> + /// \brief id<NSCopying> type.
> + QualType QIDNSCopying;
> +
> /// A flag to remember whether the implicit forms of operator new and delete
> /// have been declared.
> bool GlobalNewDeleteDeclared;
>
> -
> /// A flag that is set when parsing a -dealloc method and no [super dealloc]
> /// call was found yet.
> bool ObjCShouldCallSuperDealloc;
> @@ -1500,6 +1525,12 @@
> const PartialDiagnostic &AmbigNote,
> const PartialDiagnostic &ConvDiag,
> bool AllowScopedEnumerations);
> + enum ObjCSubscriptKind {
> + OS_Array,
> + OS_Dictionary,
> + OS_Error
> + };
> + ObjCSubscriptKind CheckSubscriptingKind(Expr *FromE);
>
> ExprResult PerformObjectMemberConversion(Expr *From,
> NestedNameSpecifier *Qualifier,
> @@ -2515,6 +2546,7 @@
> NamedDecl *D);
>
> ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
> + ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);
> ExprResult ActOnNumericConstant(const Token &Tok);
> ExprResult ActOnCharacterConstant(const Token &Tok);
> ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E);
> @@ -3232,6 +3264,10 @@
>
> /// ActOnCXXBoolLiteral - Parse {true,false} literals.
> ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
> +
> +
> + /// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.
> + ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
>
> /// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
> ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc);
> @@ -3664,7 +3700,26 @@
> ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
> Expr **Strings,
> unsigned NumStrings);
> -
> +
> + ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S);
> +
> + /// BuildObjCNumericLiteral - builds an ObjCNumericLiteral AST node for the
> + /// numeric literal expression. Type of the expression will be "NSNumber *"
> + /// or "id" if NSNumber is unavailable.
> + ExprResult BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number);
> + ExprResult ActOnObjCBoolLiteral(SourceLocation AtLoc, SourceLocation ValueLoc,
> + bool Value);
> + ExprResult BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements);
> +
> + ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
> + Expr *IndexExpr,
> + ObjCMethodDecl *getterMethod,
> + ObjCMethodDecl *setterMethod);
> +
> + ExprResult BuildObjCDictionaryLiteral(SourceRange SR,
> + ObjCDictionaryElement *Elements,
> + unsigned NumElements);
> +
> ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc,
> TypeSourceInfo *EncodedTypeInfo,
> SourceLocation RParenLoc);
>
> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Mar 6 14:05:56 2012
> @@ -1065,6 +1065,12 @@
>
> /// \brief An ObjCStringLiteral record.
> EXPR_OBJC_STRING_LITERAL,
> +
> + EXPR_OBJC_NUMERIC_LITERAL,
> + EXPR_OBJC_ARRAY_LITERAL,
> + EXPR_OBJC_DICTIONARY_LITERAL,
> +
> +
> /// \brief An ObjCEncodeExpr record.
> EXPR_OBJC_ENCODE,
> /// \brief An ObjCSelectorExpr record.
> @@ -1075,6 +1081,8 @@
> EXPR_OBJC_IVAR_REF_EXPR,
> /// \brief An ObjCPropertyRefExpr record.
> EXPR_OBJC_PROPERTY_REF_EXPR,
> + /// \brief An ObjCSubscriptRefExpr record.
> + EXPR_OBJC_SUBSCRIPT_REF_EXPR,
> /// \brief UNUSED
> EXPR_OBJC_KVC_REF_EXPR,
> /// \brief An ObjCMessageExpr record.
> @@ -1098,6 +1106,8 @@
> STMT_OBJC_AT_THROW,
> /// \brief An ObjCAutoreleasePoolStmt record.
> STMT_OBJC_AUTORELEASE_POOL,
> + /// \brief A ObjCBoolLiteralExpr record.
> + EXPR_OBJC_BOOL_LITERAL,
>
> // C++
>
>
> Modified: cfe/trunk/lib/AST/ASTContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> +++ cfe/trunk/lib/AST/ASTContext.cpp Tue Mar 6 14:05:56 2012
> @@ -477,7 +477,10 @@
> InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId);
> InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass);
> InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel);
> -
> +
> + // Builtin type for __objc_yes and __objc_no
> + ObjCBuiltinBoolTy = SignedCharTy;
> +
> ObjCConstantStringType = QualType();
>
> // void * type
>
> Modified: cfe/trunk/lib/AST/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CMakeLists.txt?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/CMakeLists.txt (original)
> +++ cfe/trunk/lib/AST/CMakeLists.txt Tue Mar 6 14:05:56 2012
> @@ -33,6 +33,7 @@
> MicrosoftCXXABI.cpp
> MicrosoftMangle.cpp
> NestedNameSpecifier.cpp
> + NSAPI.cpp
> ParentMap.cpp
> RecordLayout.cpp
> RecordLayoutBuilder.cpp
>
> Modified: cfe/trunk/lib/AST/Expr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/Expr.cpp (original)
> +++ cfe/trunk/lib/AST/Expr.cpp Tue Mar 6 14:05:56 2012
> @@ -2089,6 +2089,16 @@
> // specs.
> case ObjCMessageExprClass:
> case ObjCPropertyRefExprClass:
> + case ObjCSubscriptRefExprClass:
> + return CT_Can;
> +
> + // All the ObjC literals that are implemented as calls are
> + // potentially throwing unless we decide to close off that
> + // possibility.
> + case ObjCArrayLiteralClass:
> + case ObjCBoolLiteralExprClass:
> + case ObjCDictionaryLiteralClass:
> + case ObjCNumericLiteralClass:
> return CT_Can;
>
> // Many other things have subexpressions, so we have to test those.
> @@ -3637,6 +3647,117 @@
> ExprBits.InstantiationDependent = InstantiationDependent;
> }
>
> +ObjCArrayLiteral::ObjCArrayLiteral(llvm::ArrayRef<Expr *> Elements,
> + QualType T, ObjCMethodDecl *Method,
> + SourceRange SR)
> + : Expr(ObjCArrayLiteralClass, T, VK_RValue, OK_Ordinary,
> + false, false, false, false),
> + NumElements(Elements.size()), Range(SR), ArrayWithObjectsMethod(Method)
> +{
> + Expr **SaveElements = getElements();
> + for (unsigned I = 0, N = Elements.size(); I != N; ++I) {
> + if (Elements[I]->isTypeDependent() || Elements[I]->isValueDependent())
> + ExprBits.ValueDependent = true;
> + if (Elements[I]->isInstantiationDependent())
> + ExprBits.InstantiationDependent = true;
> + if (Elements[I]->containsUnexpandedParameterPack())
> + ExprBits.ContainsUnexpandedParameterPack = true;
> +
> + SaveElements[I] = Elements[I];
> + }
> +}
> +
> +ObjCArrayLiteral *ObjCArrayLiteral::Create(ASTContext &C,
> + llvm::ArrayRef<Expr *> Elements,
> + QualType T, ObjCMethodDecl * Method,
> + SourceRange SR) {
> + void *Mem = C.Allocate(sizeof(ObjCArrayLiteral)
> + + Elements.size() * sizeof(Expr *));
> + return new (Mem) ObjCArrayLiteral(Elements, T, Method, SR);
> +}
> +
> +ObjCArrayLiteral *ObjCArrayLiteral::CreateEmpty(ASTContext &C,
> + unsigned NumElements) {
> +
> + void *Mem = C.Allocate(sizeof(ObjCArrayLiteral)
> + + NumElements * sizeof(Expr *));
> + return new (Mem) ObjCArrayLiteral(EmptyShell(), NumElements);
> +}
> +
> +ObjCDictionaryLiteral::ObjCDictionaryLiteral(
> + ArrayRef<ObjCDictionaryElement> VK,
> + bool HasPackExpansions,
> + QualType T, ObjCMethodDecl *method,
> + SourceRange SR)
> + : Expr(ObjCDictionaryLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
> + false, false),
> + NumElements(VK.size()), HasPackExpansions(HasPackExpansions), Range(SR),
> + DictWithObjectsMethod(method)
> +{
> + KeyValuePair *KeyValues = getKeyValues();
> + ExpansionData *Expansions = getExpansionData();
> + for (unsigned I = 0; I < NumElements; I++) {
> + if (VK[I].Key->isTypeDependent() || VK[I].Key->isValueDependent() ||
> + VK[I].Value->isTypeDependent() || VK[I].Value->isValueDependent())
> + ExprBits.ValueDependent = true;
> + if (VK[I].Key->isInstantiationDependent() ||
> + VK[I].Value->isInstantiationDependent())
> + ExprBits.InstantiationDependent = true;
> + if (VK[I].EllipsisLoc.isInvalid() &&
> + (VK[I].Key->containsUnexpandedParameterPack() ||
> + VK[I].Value->containsUnexpandedParameterPack()))
> + ExprBits.ContainsUnexpandedParameterPack = true;
> +
> + KeyValues[I].Key = VK[I].Key;
> + KeyValues[I].Value = VK[I].Value;
> + if (Expansions) {
> + Expansions[I].EllipsisLoc = VK[I].EllipsisLoc;
> + if (VK[I].NumExpansions)
> + Expansions[I].NumExpansionsPlusOne = *VK[I].NumExpansions + 1;
> + else
> + Expansions[I].NumExpansionsPlusOne = 0;
> + }
> + }
> +}
> +
> +ObjCDictionaryLiteral *
> +ObjCDictionaryLiteral::Create(ASTContext &C,
> + ArrayRef<ObjCDictionaryElement> VK,
> + bool HasPackExpansions,
> + QualType T, ObjCMethodDecl *method,
> + SourceRange SR) {
> + unsigned ExpansionsSize = 0;
> + if (HasPackExpansions)
> + ExpansionsSize = sizeof(ExpansionData) * VK.size();
> +
> + void *Mem = C.Allocate(sizeof(ObjCDictionaryLiteral) +
> + sizeof(KeyValuePair) * VK.size() + ExpansionsSize);
> + return new (Mem) ObjCDictionaryLiteral(VK, HasPackExpansions, T, method, SR);
> +}
> +
> +ObjCDictionaryLiteral *
> +ObjCDictionaryLiteral::CreateEmpty(ASTContext &C, unsigned NumElements,
> + bool HasPackExpansions) {
> + unsigned ExpansionsSize = 0;
> + if (HasPackExpansions)
> + ExpansionsSize = sizeof(ExpansionData) * NumElements;
> + void *Mem = C.Allocate(sizeof(ObjCDictionaryLiteral) +
> + sizeof(KeyValuePair) * NumElements + ExpansionsSize);
> + return new (Mem) ObjCDictionaryLiteral(EmptyShell(), NumElements,
> + HasPackExpansions);
> +}
> +
> +ObjCSubscriptRefExpr *ObjCSubscriptRefExpr::Create(ASTContext &C,
> + Expr *base,
> + Expr *key, QualType T,
> + ObjCMethodDecl *getMethod,
> + ObjCMethodDecl *setMethod,
> + SourceLocation RB) {
> + void *Mem = C.Allocate(sizeof(ObjCSubscriptRefExpr));
> + return new (Mem) ObjCSubscriptRefExpr(base, key, T, VK_LValue,
> + OK_ObjCSubscript,
> + getMethod, setMethod, RB);
> +}
>
> AtomicExpr::AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr,
> QualType t, AtomicOp op, SourceLocation RP)
>
> Modified: cfe/trunk/lib/AST/ExprClassification.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ExprClassification.cpp (original)
> +++ cfe/trunk/lib/AST/ExprClassification.cpp Tue Mar 6 14:05:56 2012
> @@ -108,6 +108,7 @@
> // __func__ and friends are too.
> case Expr::PredefinedExprClass:
> // Property references are lvalues
> + case Expr::ObjCSubscriptRefExprClass:
> case Expr::ObjCPropertyRefExprClass:
> // C++ [expr.typeid]p1: The result of a typeid expression is an lvalue of...
> case Expr::CXXTypeidExprClass:
> @@ -157,6 +158,10 @@
> case Expr::ObjCSelectorExprClass:
> case Expr::ObjCProtocolExprClass:
> case Expr::ObjCStringLiteralClass:
> + case Expr::ObjCNumericLiteralClass:
> + case Expr::ObjCArrayLiteralClass:
> + case Expr::ObjCDictionaryLiteralClass:
> + case Expr::ObjCBoolLiteralExprClass:
> case Expr::ParenListExprClass:
> case Expr::SizeOfPackExprClass:
> case Expr::SubstNonTypeTemplateParmPackExprClass:
>
> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> +++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Mar 6 14:05:56 2012
> @@ -3058,6 +3058,8 @@
> bool VisitUnaryAddrOf(const UnaryOperator *E);
> bool VisitObjCStringLiteral(const ObjCStringLiteral *E)
> { return Success(E); }
> + bool VisitObjCNumericLiteral(const ObjCNumericLiteral *E)
> + { return Success(E); }
> bool VisitAddrLabelExpr(const AddrLabelExpr *E)
> { return Success(E); }
> bool VisitCallExpr(const CallExpr *E);
> @@ -4051,6 +4053,10 @@
> return Success(E->getValue(), E);
> }
>
> + bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) {
> + return Success(E->getValue(), E);
> + }
> +
> // Note, GNU defines __null as an integer, not a pointer.
> bool VisitGNUNullExpr(const GNUNullExpr *E) {
> return ZeroInitialization(E);
> @@ -6256,12 +6262,16 @@
> case Expr::CXXDependentScopeMemberExprClass:
> case Expr::UnresolvedMemberExprClass:
> case Expr::ObjCStringLiteralClass:
> + case Expr::ObjCNumericLiteralClass:
> + case Expr::ObjCArrayLiteralClass:
> + case Expr::ObjCDictionaryLiteralClass:
> case Expr::ObjCEncodeExprClass:
> case Expr::ObjCMessageExprClass:
> case Expr::ObjCSelectorExprClass:
> case Expr::ObjCProtocolExprClass:
> case Expr::ObjCIvarRefExprClass:
> case Expr::ObjCPropertyRefExprClass:
> + case Expr::ObjCSubscriptRefExprClass:
> case Expr::ObjCIsaExprClass:
> case Expr::ShuffleVectorExprClass:
> case Expr::BlockExprClass:
> @@ -6294,6 +6304,7 @@
> return CheckICE(cast<GenericSelectionExpr>(E)->getResultExpr(), Ctx);
> case Expr::IntegerLiteralClass:
> case Expr::CharacterLiteralClass:
> + case Expr::ObjCBoolLiteralExprClass:
> case Expr::CXXBoolLiteralExprClass:
> case Expr::CXXScalarValueInitExprClass:
> case Expr::UnaryTypeTraitExprClass:
>
> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue Mar 6 14:05:56 2012
> @@ -2374,6 +2374,10 @@
> case Expr::ObjCProtocolExprClass:
> case Expr::ObjCSelectorExprClass:
> case Expr::ObjCStringLiteralClass:
> + case Expr::ObjCNumericLiteralClass:
> + case Expr::ObjCArrayLiteralClass:
> + case Expr::ObjCDictionaryLiteralClass:
> + case Expr::ObjCSubscriptRefExprClass:
> case Expr::ObjCIndirectCopyRestoreExprClass:
> case Expr::OffsetOfExprClass:
> case Expr::PredefinedExprClass:
> @@ -2814,6 +2818,13 @@
> Out << 'E';
> break;
>
> + // FIXME. __objc_yes/__objc_no are mangled same as true/false
> + case Expr::ObjCBoolLiteralExprClass:
> + Out << "Lb";
> + Out << (cast<ObjCBoolLiteralExpr>(E)->getValue() ? '1' : '0');
> + Out << 'E';
> + break;
> +
> case Expr::CXXBoolLiteralExprClass:
> Out << "Lb";
> Out << (cast<CXXBoolLiteralExpr>(E)->getValue() ? '1' : '0');
>
> Added: cfe/trunk/lib/AST/NSAPI.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/NSAPI.cpp?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/lib/AST/NSAPI.cpp (added)
> +++ cfe/trunk/lib/AST/NSAPI.cpp Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,311 @@
> +//===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "clang/AST/NSAPI.h"
> +#include "clang/AST/ASTContext.h"
> +
> +using namespace clang;
> +
> +NSAPI::NSAPI(ASTContext &ctx)
> + : Ctx(ctx), ClassIds() {
> +}
> +
> +IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
> + static const char *ClassName[NumClassIds] = {
> + "NSString",
> + "NSArray",
> + "NSMutableArray",
> + "NSDictionary",
> + "NSMutableDictionary",
> + "NSNumber"
> + };
> +
> + if (!ClassIds[K])
> + return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
> +
> + return ClassIds[K];
> +}
> +
> +Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
> + if (NSStringSelectors[MK].isNull()) {
> + Selector Sel;
> + switch (MK) {
> + case NSStr_stringWithString:
> + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
> + break;
> + case NSStr_initWithString:
> + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
> + break;
> + }
> + return (NSStringSelectors[MK] = Sel);
> + }
> +
> + return NSStringSelectors[MK];
> +}
> +
> +Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
> + if (NSArraySelectors[MK].isNull()) {
> + Selector Sel;
> + switch (MK) {
> + case NSArr_array:
> + Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
> + break;
> + case NSArr_arrayWithArray:
> + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
> + break;
> + case NSArr_arrayWithObject:
> + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
> + break;
> + case NSArr_arrayWithObjects:
> + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
> + break;
> + case NSArr_arrayWithObjectsCount: {
> + IdentifierInfo *KeyIdents[] = {
> + &Ctx.Idents.get("arrayWithObjects"),
> + &Ctx.Idents.get("count")
> + };
> + Sel = Ctx.Selectors.getSelector(2, KeyIdents);
> + break;
> + }
> + case NSArr_initWithArray:
> + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
> + break;
> + case NSArr_initWithObjects:
> + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
> + break;
> + case NSArr_objectAtIndex:
> + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
> + break;
> + case NSMutableArr_replaceObjectAtIndex: {
> + IdentifierInfo *KeyIdents[] = {
> + &Ctx.Idents.get("replaceObjectAtIndex"),
> + &Ctx.Idents.get("withObject")
> + };
> + Sel = Ctx.Selectors.getSelector(2, KeyIdents);
> + break;
> + }
> + }
> + return (NSArraySelectors[MK] = Sel);
> + }
> +
> + return NSArraySelectors[MK];
> +}
> +
> +llvm::Optional<NSAPI::NSArrayMethodKind>
> +NSAPI::getNSArrayMethodKind(Selector Sel) {
> + for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
> + NSArrayMethodKind MK = NSArrayMethodKind(i);
> + if (Sel == getNSArraySelector(MK))
> + return MK;
> + }
> +
> + return llvm::Optional<NSArrayMethodKind>();
> +}
> +
> +Selector NSAPI::getNSDictionarySelector(
> + NSDictionaryMethodKind MK) const {
> + if (NSDictionarySelectors[MK].isNull()) {
> + Selector Sel;
> + switch (MK) {
> + case NSDict_dictionary:
> + Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
> + break;
> + case NSDict_dictionaryWithDictionary:
> + Sel = Ctx.Selectors.getUnarySelector(
> + &Ctx.Idents.get("dictionaryWithDictionary"));
> + break;
> + case NSDict_dictionaryWithObjectForKey: {
> + IdentifierInfo *KeyIdents[] = {
> + &Ctx.Idents.get("dictionaryWithObject"),
> + &Ctx.Idents.get("forKey")
> + };
> + Sel = Ctx.Selectors.getSelector(2, KeyIdents);
> + break;
> + }
> + case NSDict_dictionaryWithObjectsForKeys: {
> + IdentifierInfo *KeyIdents[] = {
> + &Ctx.Idents.get("dictionaryWithObjects"),
> + &Ctx.Idents.get("forKeys")
> + };
> + Sel = Ctx.Selectors.getSelector(2, KeyIdents);
> + break;
> + }
> + case NSDict_dictionaryWithObjectsForKeysCount: {
> + IdentifierInfo *KeyIdents[] = {
> + &Ctx.Idents.get("dictionaryWithObjects"),
> + &Ctx.Idents.get("forKeys"),
> + &Ctx.Idents.get("count")
> + };
> + Sel = Ctx.Selectors.getSelector(3, KeyIdents);
> + break;
> + }
> + case NSDict_dictionaryWithObjectsAndKeys:
> + Sel = Ctx.Selectors.getUnarySelector(
> + &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
> + break;
> + case NSDict_initWithDictionary:
> + Sel = Ctx.Selectors.getUnarySelector(
> + &Ctx.Idents.get("initWithDictionary"));
> + break;
> + case NSDict_initWithObjectsAndKeys:
> + Sel = Ctx.Selectors.getUnarySelector(
> + &Ctx.Idents.get("initWithObjectsAndKeys"));
> + break;
> + case NSDict_objectForKey:
> + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
> + break;
> + case NSMutableDict_setObjectForKey: {
> + IdentifierInfo *KeyIdents[] = {
> + &Ctx.Idents.get("setObject"),
> + &Ctx.Idents.get("forKey")
> + };
> + Sel = Ctx.Selectors.getSelector(2, KeyIdents);
> + break;
> + }
> + }
> + return (NSDictionarySelectors[MK] = Sel);
> + }
> +
> + return NSDictionarySelectors[MK];
> +}
> +
> +llvm::Optional<NSAPI::NSDictionaryMethodKind>
> +NSAPI::getNSDictionaryMethodKind(Selector Sel) {
> + for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
> + NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
> + if (Sel == getNSDictionarySelector(MK))
> + return MK;
> + }
> +
> + return llvm::Optional<NSDictionaryMethodKind>();
> +}
> +
> +Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
> + bool Instance) const {
> + static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
> + "numberWithChar",
> + "numberWithUnsignedChar",
> + "numberWithShort",
> + "numberWithUnsignedShort",
> + "numberWithInt",
> + "numberWithUnsignedInt",
> + "numberWithLong",
> + "numberWithUnsignedLong",
> + "numberWithLongLong",
> + "numberWithUnsignedLongLong",
> + "numberWithFloat",
> + "numberWithDouble",
> + "numberWithBool",
> + "numberWithInteger",
> + "numberWithUnsignedInteger"
> + };
> + static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
> + "initWithChar",
> + "initWithUnsignedChar",
> + "initWithShort",
> + "initWithUnsignedShort",
> + "initWithInt",
> + "initWithUnsignedInt",
> + "initWithLong",
> + "initWithUnsignedLong",
> + "initWithLongLong",
> + "initWithUnsignedLongLong",
> + "initWithFloat",
> + "initWithDouble",
> + "initWithBool",
> + "initWithInteger",
> + "initWithUnsignedInteger"
> + };
> +
> + Selector *Sels;
> + const char **Names;
> + if (Instance) {
> + Sels = NSNumberInstanceSelectors;
> + Names = InstanceSelectorName;
> + } else {
> + Sels = NSNumberClassSelectors;
> + Names = ClassSelectorName;
> + }
> +
> + if (Sels[MK].isNull())
> + Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
> + return Sels[MK];
> +}
> +
> +llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
> +NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
> + for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
> + NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
> + if (isNSNumberLiteralSelector(MK, Sel))
> + return MK;
> + }
> +
> + return llvm::Optional<NSNumberLiteralMethodKind>();
> +}
> +
> +llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
> +NSAPI::getNSNumberFactoryMethodKind(QualType T) {
> + const BuiltinType *BT = T->getAs<BuiltinType>();
> + if (!BT)
> + return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
> +
> + switch (BT->getKind()) {
> + case BuiltinType::Char_S:
> + case BuiltinType::SChar:
> + return NSAPI::NSNumberWithChar;
> + case BuiltinType::Char_U:
> + case BuiltinType::UChar:
> + return NSAPI::NSNumberWithUnsignedChar;
> + case BuiltinType::Short:
> + return NSAPI::NSNumberWithShort;
> + case BuiltinType::UShort:
> + return NSAPI::NSNumberWithUnsignedShort;
> + case BuiltinType::Int:
> + return NSAPI::NSNumberWithInt;
> + case BuiltinType::UInt:
> + return NSAPI::NSNumberWithUnsignedInt;
> + case BuiltinType::Long:
> + return NSAPI::NSNumberWithLong;
> + case BuiltinType::ULong:
> + return NSAPI::NSNumberWithUnsignedLong;
> + case BuiltinType::LongLong:
> + return NSAPI::NSNumberWithLongLong;
> + case BuiltinType::ULongLong:
> + return NSAPI::NSNumberWithUnsignedLongLong;
> + case BuiltinType::Float:
> + return NSAPI::NSNumberWithFloat;
> + case BuiltinType::Double:
> + return NSAPI::NSNumberWithDouble;
> + case BuiltinType::Bool:
> + return NSAPI::NSNumberWithBool;
> +
> + case BuiltinType::Void:
> + case BuiltinType::WChar_U:
> + case BuiltinType::WChar_S:
> + case BuiltinType::Char16:
> + case BuiltinType::Char32:
> + case BuiltinType::Int128:
> + case BuiltinType::LongDouble:
> + case BuiltinType::UInt128:
> + case BuiltinType::NullPtr:
> + case BuiltinType::ObjCClass:
> + case BuiltinType::ObjCId:
> + case BuiltinType::ObjCSel:
> + case BuiltinType::BoundMember:
> + case BuiltinType::Dependent:
> + case BuiltinType::Overload:
> + case BuiltinType::UnknownAny:
> + case BuiltinType::ARCUnbridgedCast:
> + case BuiltinType::Half:
> + case BuiltinType::PseudoObject:
> + break;
> + }
> +
> + return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
> +}
>
> Modified: cfe/trunk/lib/AST/StmtDumper.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtDumper.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/StmtDumper.cpp (original)
> +++ cfe/trunk/lib/AST/StmtDumper.cpp Tue Mar 6 14:05:56 2012
> @@ -112,6 +112,7 @@
> case OK_Ordinary: break;
> case OK_BitField: OS << " bitfield"; break;
> case OK_ObjCProperty: OS << " objcproperty"; break;
> + case OK_ObjCSubscript: OS << " objcsubscript"; break;
> case OK_VectorComponent: OS << " vectorcomponent"; break;
> }
> }
> @@ -168,7 +169,9 @@
> void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
> void VisitObjCProtocolExpr(ObjCProtocolExpr *Node);
> void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node);
> + void VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node);
> void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
> + void VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node);
> };
> }
>
> @@ -682,6 +685,32 @@
> OS << " super";
> }
>
> +void StmtDumper::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) {
> + DumpExpr(Node);
> + if (Node->isArraySubscriptRefExpr())
> + OS << " Kind=ArraySubscript GetterForArray=\"";
> + else
> + OS << " Kind=DictionarySubscript GetterForDictionary=\"";
> + if (Node->getAtIndexMethodDecl())
> + OS << Node->getAtIndexMethodDecl()->getSelector().getAsString();
> + else
> + OS << "(null)";
> +
> + if (Node->isArraySubscriptRefExpr())
> + OS << "\" SetterForArray=\"";
> + else
> + OS << "\" SetterForDictionary=\"";
> + if (Node->setAtIndexMethodDecl())
> + OS << Node->setAtIndexMethodDecl()->getSelector().getAsString();
> + else
> + OS << "(null)";
> +}
> +
> +void StmtDumper::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node) {
> + DumpExpr(Node);
> + OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no");
> +}
> +
> //===----------------------------------------------------------------------===//
> // Stmt method implementations
> //===----------------------------------------------------------------------===//
>
> Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
> +++ cfe/trunk/lib/AST/StmtPrinter.cpp Tue Mar 6 14:05:56 2012
> @@ -603,6 +603,14 @@
> OS << Node->getExplicitProperty()->getName();
> }
>
> +void StmtPrinter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) {
> +
> + PrintExpr(Node->getBaseExpr());
> + OS << "[";
> + PrintExpr(Node->getKeyExpr());
> + OS << "]";
> +}
> +
> void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
> switch (Node->getIdentType()) {
> default:
> @@ -1646,6 +1654,41 @@
> VisitStringLiteral(Node->getString());
> }
>
> +void StmtPrinter::VisitObjCNumericLiteral(ObjCNumericLiteral *E) {
> + OS << "@";
> + Visit(E->getNumber());
> +}
> +
> +void StmtPrinter::VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
> + OS << "@[ ";
> + StmtRange ch = E->children();
> + if (ch.first != ch.second) {
> + while (1) {
> + Visit(*ch.first);
> + ++ch.first;
> + if (ch.first == ch.second) break;
> + OS << ", ";
> + }
> + }
> + OS << " ]";
> +}
> +
> +void StmtPrinter::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
> + OS << "@{ ";
> + for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) {
> + if (I > 0)
> + OS << ", ";
> +
> + ObjCDictionaryElement Element = E->getKeyValueElement(I);
> + Visit(Element.Key);
> + OS << " : ";
> + Visit(Element.Value);
> + if (Element.isPackExpansion())
> + OS << "...";
> + }
> + OS << " }";
> +}
> +
> void StmtPrinter::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
> OS << "@encode(" << Node->getEncodedType().getAsString(Policy) << ')';
> }
> @@ -1696,6 +1739,10 @@
> OS << "]";
> }
>
> +void StmtPrinter::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node) {
> + OS << (Node->getValue() ? "__objc_yes" : "__objc_no");
> +}
> +
> void
> StmtPrinter::VisitObjCIndirectCopyRestoreExpr(ObjCIndirectCopyRestoreExpr *E) {
> PrintExpr(E->getSubExpr());
>
> Modified: cfe/trunk/lib/AST/StmtProfile.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/StmtProfile.cpp (original)
> +++ cfe/trunk/lib/AST/StmtProfile.cpp Tue Mar 6 14:05:56 2012
> @@ -978,6 +978,18 @@
> VisitExpr(S);
> }
>
> +void StmtProfiler::VisitObjCNumericLiteral(const ObjCNumericLiteral *E) {
> + VisitExpr(E);
> +}
> +
> +void StmtProfiler::VisitObjCArrayLiteral(const ObjCArrayLiteral *E) {
> + VisitExpr(E);
> +}
> +
> +void StmtProfiler::VisitObjCDictionaryLiteral(const ObjCDictionaryLiteral *E) {
> + VisitExpr(E);
> +}
> +
> void StmtProfiler::VisitObjCEncodeExpr(const ObjCEncodeExpr *S) {
> VisitExpr(S);
> VisitType(S->getEncodedType());
> @@ -1014,6 +1026,12 @@
> }
> }
>
> +void StmtProfiler::VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *S) {
> + VisitExpr(S);
> + VisitDecl(S->getAtIndexMethodDecl());
> + VisitDecl(S->setAtIndexMethodDecl());
> +}
> +
> void StmtProfiler::VisitObjCMessageExpr(const ObjCMessageExpr *S) {
> VisitExpr(S);
> VisitName(S->getSelector());
> @@ -1025,6 +1043,11 @@
> ID.AddBoolean(S->isArrow());
> }
>
> +void StmtProfiler::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *S) {
> + VisitExpr(S);
> + ID.AddBoolean(S->getValue());
> +}
> +
> void StmtProfiler::VisitObjCIndirectCopyRestoreExpr(
> const ObjCIndirectCopyRestoreExpr *S) {
> VisitExpr(S);
>
> Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Tue Mar 6 14:05:56 2012
> @@ -177,6 +177,9 @@
> Value *VisitCharacterLiteral(const CharacterLiteral *E) {
> return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
> }
> + Value *VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) {
> + return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
> + }
> Value *VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) {
> return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
> }
> @@ -519,6 +522,15 @@
> Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) {
> return CGF.EmitObjCStringLiteral(E);
> }
> + Value *VisitObjCNumericLiteral(ObjCNumericLiteral *E) {
> + return CGF.EmitObjCNumericLiteral(E);
> + }
> + Value *VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
> + return CGF.EmitObjCArrayLiteral(E);
> + }
> + Value *VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
> + return CGF.EmitObjCDictionaryLiteral(E);
> + }
> Value *VisitAsTypeExpr(AsTypeExpr *CE);
> Value *VisitAtomicExpr(AtomicExpr *AE);
> };
>
> Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Tue Mar 6 14:05:56 2012
> @@ -29,6 +29,10 @@
> typedef llvm::PointerIntPair<llvm::Value*,1,bool> TryEmitResult;
> static TryEmitResult
> tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e);
> +static RValue AdjustRelatedResultType(CodeGenFunction &CGF,
> + const Expr *E,
> + const ObjCMethodDecl *Method,
> + RValue Result);
>
> /// Given the address of a variable of pointer type, find the correct
> /// null to store into it.
> @@ -47,6 +51,138 @@
> return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
> }
>
> +/// EmitObjCNumericLiteral - This routine generates code for
> +/// the appropriate +[NSNumber numberWith<Type>:] method.
> +///
> +llvm::Value *CodeGenFunction::EmitObjCNumericLiteral(const ObjCNumericLiteral *E) {
> + // Generate the correct selector for this literal's concrete type.
> + const Expr *NL = E->getNumber();
> + // Get the method.
> + const ObjCMethodDecl *Method = E->getObjCNumericLiteralMethod();
> + assert(Method && "NSNumber method is null");
> + Selector Sel = Method->getSelector();
> +
> + // Generate a reference to the class pointer, which will be the receiver.
> + QualType ResultType = E->getType(); // should be NSNumber *
> + const ObjCObjectPointerType *InterfacePointerType =
> + ResultType->getAsObjCInterfacePointerType();
> + ObjCInterfaceDecl *NSNumberDecl =
> + InterfacePointerType->getObjectType()->getInterface();
> + CGObjCRuntime &Runtime = CGM.getObjCRuntime();
> + llvm::Value *Receiver = Runtime.GetClass(Builder, NSNumberDecl);
> +
> + const ParmVarDecl *argDecl = *Method->param_begin();
> + QualType ArgQT = argDecl->getType().getUnqualifiedType();
> + RValue RV = EmitAnyExpr(NL);
> + CallArgList Args;
> + Args.add(RV, ArgQT);
> +
> + RValue result = Runtime.GenerateMessageSend(*this, ReturnValueSlot(),
> + ResultType, Sel, Receiver, Args,
> + NSNumberDecl, Method);
> + return Builder.CreateBitCast(result.getScalarVal(),
> + ConvertType(E->getType()));
> +}
> +
> +llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
> + const ObjCMethodDecl *MethodWithObjects) {
> + ASTContext &Context = CGM.getContext();
> + const ObjCDictionaryLiteral *DLE = 0;
> + const ObjCArrayLiteral *ALE = dyn_cast<ObjCArrayLiteral>(E);
> + if (!ALE)
> + DLE = cast<ObjCDictionaryLiteral>(E);
> +
> + // Compute the type of the array we're initializing.
> + uint64_t NumElements =
> + ALE ? ALE->getNumElements() : DLE->getNumElements();
> + llvm::APInt APNumElements(Context.getTypeSize(Context.getSizeType()),
> + NumElements);
> + QualType ElementType = Context.getObjCIdType().withConst();
> + QualType ElementArrayType
> + = Context.getConstantArrayType(ElementType, APNumElements,
> + ArrayType::Normal, /*IndexTypeQuals=*/0);
> +
> + // Allocate the temporary array(s).
> + llvm::Value *Objects = CreateMemTemp(ElementArrayType, "objects");
> + llvm::Value *Keys = 0;
> + if (DLE)
> + Keys = CreateMemTemp(ElementArrayType, "keys");
> +
> + // Perform the actual initialialization of the array(s).
> + for (uint64_t i = 0; i < NumElements; i++) {
> + if (ALE) {
> + // Emit the initializer.
> + const Expr *Rhs = ALE->getElement(i);
> + LValue LV = LValue::MakeAddr(Builder.CreateStructGEP(Objects, i),
> + ElementType,
> + Context.getTypeAlignInChars(Rhs->getType()),
> + Context);
> + EmitScalarInit(Rhs, /*D=*/0, LV, /*capturedByInit=*/false);
> + } else {
> + // Emit the key initializer.
> + const Expr *Key = DLE->getKeyValueElement(i).Key;
> + LValue KeyLV = LValue::MakeAddr(Builder.CreateStructGEP(Keys, i),
> + ElementType,
> + Context.getTypeAlignInChars(Key->getType()),
> + Context);
> + EmitScalarInit(Key, /*D=*/0, KeyLV, /*capturedByInit=*/false);
> +
> + // Emit the value initializer.
> + const Expr *Value = DLE->getKeyValueElement(i).Value;
> + LValue ValueLV = LValue::MakeAddr(Builder.CreateStructGEP(Objects, i),
> + ElementType,
> + Context.getTypeAlignInChars(Value->getType()),
> + Context);
> + EmitScalarInit(Value, /*D=*/0, ValueLV, /*capturedByInit=*/false);
> + }
> + }
> +
> + // Generate the argument list.
> + CallArgList Args;
> + ObjCMethodDecl::param_const_iterator PI = MethodWithObjects->param_begin();
> + const ParmVarDecl *argDecl = *PI++;
> + QualType ArgQT = argDecl->getType().getUnqualifiedType();
> + Args.add(RValue::get(Objects), ArgQT);
> + if (DLE) {
> + argDecl = *PI++;
> + ArgQT = argDecl->getType().getUnqualifiedType();
> + Args.add(RValue::get(Keys), ArgQT);
> + }
> + argDecl = *PI;
> + ArgQT = argDecl->getType().getUnqualifiedType();
> + llvm::Value *Count =
> + llvm::ConstantInt::get(CGM.getTypes().ConvertType(ArgQT), NumElements);
> + Args.add(RValue::get(Count), ArgQT);
> +
> + // Generate a reference to the class pointer, which will be the receiver.
> + Selector Sel = MethodWithObjects->getSelector();
> + QualType ResultType = E->getType();
> + const ObjCObjectPointerType *InterfacePointerType
> + = ResultType->getAsObjCInterfacePointerType();
> + ObjCInterfaceDecl *Class
> + = InterfacePointerType->getObjectType()->getInterface();
> + CGObjCRuntime &Runtime = CGM.getObjCRuntime();
> + llvm::Value *Receiver = Runtime.GetClass(Builder, Class);
> +
> + // Generate the message send.
> + RValue result = Runtime.GenerateMessageSend(*this, ReturnValueSlot(),
> + MethodWithObjects->getResultType(),
> + Sel,
> + Receiver, Args, Class,
> + MethodWithObjects);
> + return Builder.CreateBitCast(result.getScalarVal(),
> + ConvertType(E->getType()));
> +}
> +
> +llvm::Value *CodeGenFunction::EmitObjCArrayLiteral(const ObjCArrayLiteral *E) {
> + return EmitObjCCollectionLiteral(E, E->getArrayWithObjectsMethod());
> +}
> +
> +llvm::Value *CodeGenFunction::EmitObjCDictionaryLiteral(
> + const ObjCDictionaryLiteral *E) {
> + return EmitObjCCollectionLiteral(E, E->getDictWithObjectsMethod());
> +}
> +
> /// Emit a selector.
> llvm::Value *CodeGenFunction::EmitObjCSelectorExpr(const ObjCSelectorExpr *E) {
> // Untyped selector.
> @@ -884,6 +1020,26 @@
> return false;
> }
>
> +bool UseOptimizedSetter(CodeGenModule &CGM) {
> + if (CGM.getLangOptions().getGC() != LangOptions::NonGC)
> + return false;
> + const TargetInfo &Target = CGM.getContext().getTargetInfo();
> + StringRef TargetPlatform = Target.getPlatformName();
> + if (TargetPlatform.empty())
> + return false;
> + VersionTuple TargetMinVersion = Target.getPlatformMinVersion();
> +
> + if (TargetPlatform.compare("macosx") ||
> + TargetMinVersion.getMajor() <= 9)
> + return false;
> +
> + unsigned minor = 0;
> + if (llvm::Optional<unsigned> Minor = TargetMinVersion.getMinor())
> + minor = *Minor;
> +
> + return (minor >= 8);
> +}
> +
> void
> CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
> const ObjCPropertyImplDecl *propImpl,
> @@ -937,13 +1093,27 @@
>
> case PropertyImplStrategy::GetSetProperty:
> case PropertyImplStrategy::SetPropertyAndExpressionGet: {
> - llvm::Value *setPropertyFn =
> - CGM.getObjCRuntime().GetPropertySetFunction();
> - if (!setPropertyFn) {
> - CGM.ErrorUnsupported(propImpl, "Obj-C setter requiring atomic copy");
> - return;
> +
> + llvm::Value *setOptimizedPropertyFn = 0;
> + llvm::Value *setPropertyFn = 0;
> + if (UseOptimizedSetter(CGM)) {
> + // 10.8 code and GC is off
> + setOptimizedPropertyFn =
> + CGM.getObjCRuntime().GetOptimizedPropertySetFunction(strategy.isAtomic(),
> + strategy.isCopy());
> + if (!setOptimizedPropertyFn) {
> + CGM.ErrorUnsupported(propImpl, "Obj-C optimized setter - NYI");
> + return;
> + }
> }
> -
> + else {
> + setPropertyFn = CGM.getObjCRuntime().GetPropertySetFunction();
> + if (!setPropertyFn) {
> + CGM.ErrorUnsupported(propImpl, "Obj-C setter requiring atomic copy");
> + return;
> + }
> + }
> +
> // Emit objc_setProperty((id) self, _cmd, offset, arg,
> // <is-atomic>, <is-copy>).
> llvm::Value *cmd =
> @@ -958,18 +1128,28 @@
> CallArgList args;
> args.add(RValue::get(self), getContext().getObjCIdType());
> args.add(RValue::get(cmd), getContext().getObjCSelType());
> - args.add(RValue::get(ivarOffset), getContext().getPointerDiffType());
> - args.add(RValue::get(arg), getContext().getObjCIdType());
> - args.add(RValue::get(Builder.getInt1(strategy.isAtomic())),
> - getContext().BoolTy);
> - args.add(RValue::get(Builder.getInt1(strategy.isCopy())),
> - getContext().BoolTy);
> - // FIXME: We shouldn't need to get the function info here, the runtime
> - // already should have computed it to build the function.
> - EmitCall(getTypes().arrangeFunctionCall(getContext().VoidTy, args,
> - FunctionType::ExtInfo(),
> - RequiredArgs::All),
> - setPropertyFn, ReturnValueSlot(), args);
> + if (setOptimizedPropertyFn) {
> + args.add(RValue::get(arg), getContext().getObjCIdType());
> + args.add(RValue::get(ivarOffset), getContext().getPointerDiffType());
> + EmitCall(getTypes().arrangeFunctionCall(getContext().VoidTy, args,
> + FunctionType::ExtInfo(),
> + RequiredArgs::All),
> + setOptimizedPropertyFn, ReturnValueSlot(), args);
> + } else {
> + args.add(RValue::get(ivarOffset), getContext().getPointerDiffType());
> + args.add(RValue::get(arg), getContext().getObjCIdType());
> + args.add(RValue::get(Builder.getInt1(strategy.isAtomic())),
> + getContext().BoolTy);
> + args.add(RValue::get(Builder.getInt1(strategy.isCopy())),
> + getContext().BoolTy);
> + // FIXME: We shouldn't need to get the function info here, the runtime
> + // already should have computed it to build the function.
> + EmitCall(getTypes().arrangeFunctionCall(getContext().VoidTy, args,
> + FunctionType::ExtInfo(),
> + RequiredArgs::All),
> + setPropertyFn, ReturnValueSlot(), args);
> + }
> +
> return;
> }
>
>
> Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Tue Mar 6 14:05:56 2012
> @@ -472,6 +472,8 @@
> virtual llvm::Function *ModuleInitFunction();
> virtual llvm::Constant *GetPropertyGetFunction();
> virtual llvm::Constant *GetPropertySetFunction();
> + virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
> + bool copy);
> virtual llvm::Constant *GetSetStructFunction();
> virtual llvm::Constant *GetCppAtomicObjectFunction();
> virtual llvm::Constant *GetGetStructFunction();
> @@ -2427,6 +2429,11 @@
> return SetPropertyFn;
> }
>
> +llvm::Constant *CGObjCGNU::GetOptimizedPropertySetFunction(bool atomic,
> + bool copy) {
> + return 0;
> +}
> +
> llvm::Constant *CGObjCGNU::GetGetStructFunction() {
> return GetStructPropertyFn;
> }
>
> Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Tue Mar 6 14:05:56 2012
> @@ -267,6 +267,41 @@
> return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
> }
>
> + llvm::Constant *getOptimizedSetPropertyFn(bool atomic, bool copy) {
> + CodeGen::CodeGenTypes &Types = CGM.getTypes();
> + ASTContext &Ctx = CGM.getContext();
> + // void objc_setProperty_atomic(id self, SEL _cmd,
> + // id newValue, ptrdiff_t offset);
> + // void objc_setProperty_nonatomic(id self, SEL _cmd,
> + // id newValue, ptrdiff_t offset);
> + // void objc_setProperty_atomic_copy(id self, SEL _cmd,
> + // id newValue, ptrdiff_t offset);
> + // void objc_setProperty_nonatomic_copy(id self, SEL _cmd,
> + // id newValue, ptrdiff_t offset);
> +
> + SmallVector<CanQualType,4> Params;
> + CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
> + CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
> + Params.push_back(IdType);
> + Params.push_back(SelType);
> + Params.push_back(IdType);
> + Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
> + llvm::FunctionType *FTy =
> + Types.GetFunctionType(Types.arrangeFunctionType(Ctx.VoidTy, Params,
> + FunctionType::ExtInfo(),
> + RequiredArgs::All));
> + const char *name;
> + if (atomic && copy)
> + name = "objc_setProperty_atomic_copy";
> + else if (atomic && !copy)
> + name = "objc_setProperty_atomic";
> + else if (!atomic && copy)
> + name = "objc_setProperty_nonatomic_copy";
> + else
> + name = "objc_setProperty_nonatomic";
> +
> + return CGM.CreateRuntimeFunction(FTy, name);
> + }
>
> llvm::Constant *getCopyStructFn() {
> CodeGen::CodeGenTypes &Types = CGM.getTypes();
> @@ -906,7 +941,7 @@
> CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
>
> virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
> -
> +
> virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
> const ObjCContainerDecl *CD=0);
>
> @@ -1087,6 +1122,8 @@
>
> virtual llvm::Constant *GetPropertyGetFunction();
> virtual llvm::Constant *GetPropertySetFunction();
> + virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
> + bool copy);
> virtual llvm::Constant *GetGetStructFunction();
> virtual llvm::Constant *GetSetStructFunction();
> virtual llvm::Constant *GetCppAtomicObjectFunction();
> @@ -1349,6 +1386,11 @@
> return ObjCTypes.getSetPropertyFn();
> }
>
> + virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
> + bool copy) {
> + return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
> + }
> +
> virtual llvm::Constant *GetSetStructFunction() {
> return ObjCTypes.getCopyStructFn();
> }
> @@ -1578,6 +1620,10 @@
> CGM.GetAddrOfConstantString(SL));
> }
>
> +enum {
> + kCFTaggedObjectID_Integer = (1 << 1) + 1
> +};
> +
> /// Generates a message send where the super is the receiver. This is
> /// a message send to self with special delivery semantics indicating
> /// which class's method should be called.
> @@ -2723,6 +2769,11 @@
> return ObjCTypes.getSetPropertyFn();
> }
>
> +llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
> + bool copy) {
> + return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
> +}
> +
> llvm::Constant *CGObjCMac::GetGetStructFunction() {
> return ObjCTypes.getCopyStructFn();
> }
>
> Modified: cfe/trunk/lib/CodeGen/CGObjCRuntime.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCRuntime.h?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGObjCRuntime.h (original)
> +++ cfe/trunk/lib/CodeGen/CGObjCRuntime.h Tue Mar 6 14:05:56 2012
> @@ -135,7 +135,7 @@
>
> /// Generate a constant string object.
> virtual llvm::Constant *GenerateConstantString(const StringLiteral *) = 0;
> -
> +
> /// Generate a category. A category contains a list of methods (and
> /// accompanying metadata) and a list of protocols.
> virtual void GenerateCategory(const ObjCCategoryImplDecl *OCD) = 0;
> @@ -202,6 +202,10 @@
> /// Return the runtime function for setting properties.
> virtual llvm::Constant *GetPropertySetFunction() = 0;
>
> + /// Return the runtime function for optimized setting properties.
> + virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
> + bool copy) = 0;
> +
> // API for atomic copying of qualified aggregates in getter.
> virtual llvm::Constant *GetGetStructFunction() = 0;
> // API for atomic copying of qualified aggregates in setter.
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Mar 6 14:05:56 2012
> @@ -2238,6 +2238,11 @@
>
> llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E);
> llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E);
> + llvm::Value *EmitObjCNumericLiteral(const ObjCNumericLiteral *E);
> + llvm::Value *EmitObjCArrayLiteral(const ObjCArrayLiteral *E);
> + llvm::Value *EmitObjCDictionaryLiteral(const ObjCDictionaryLiteral *E);
> + llvm::Value *EmitObjCCollectionLiteral(const Expr *E,
> + const ObjCMethodDecl *MethodWithObjects);
> llvm::Value *EmitObjCSelectorExpr(const ObjCSelectorExpr *E);
> RValue EmitObjCMessageExpr(const ObjCMessageExpr *E,
> ReturnValueSlot Return = ReturnValueSlot());
>
> Modified: cfe/trunk/lib/Driver/ToolChains.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Driver/ToolChains.cpp (original)
> +++ cfe/trunk/lib/Driver/ToolChains.cpp Tue Mar 6 14:05:56 2012
> @@ -93,12 +93,17 @@
> return !isMacosxVersionLT(10, 7);
> }
>
> +bool Darwin::hasSubscriptingRuntime() const {
> + return !isTargetIPhoneOS() && !isMacosxVersionLT(10, 8);
> +}
> +
> /// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
> void Darwin::configureObjCRuntime(ObjCRuntime &runtime) const {
> if (runtime.getKind() != ObjCRuntime::NeXT)
> return ToolChain::configureObjCRuntime(runtime);
>
> runtime.HasARC = runtime.HasWeak = hasARCRuntime();
> + runtime.HasSubscripting = hasSubscriptingRuntime();
>
> // So far, objc_terminate is only available in iOS 5.
> // FIXME: do the simulator logic properly.
>
> Modified: cfe/trunk/lib/Driver/ToolChains.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.h?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Driver/ToolChains.h (original)
> +++ cfe/trunk/lib/Driver/ToolChains.h Tue Mar 6 14:05:56 2012
> @@ -205,6 +205,7 @@
> std::string MacosxVersionMin;
>
> bool hasARCRuntime() const;
> + bool hasSubscriptingRuntime() const;
>
> private:
> void AddDeploymentTarget(DerivedArgList &Args) const;
> @@ -252,6 +253,12 @@
> return TargetIsIPhoneOSSimulator;
> }
>
> + bool isTargetMacOS() const {
> + return !isTargetIOSSimulator() &&
> + !isTargetIPhoneOS() &&
> + ARCRuntimeForSimulator == ARCSimulator_None;
> + }
> +
> bool isTargetInitialized() const { return TargetInitialized; }
>
> void getTargetVersion(unsigned (&Res)[3]) const {
>
> Modified: cfe/trunk/lib/Driver/Tools.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Driver/Tools.cpp (original)
> +++ cfe/trunk/lib/Driver/Tools.cpp Tue Mar 6 14:05:56 2012
> @@ -136,6 +136,13 @@
> return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false);
> }
>
> +/// \brief Determine whether we are linking the ObjC runtime.
> +static bool isObjCRuntimeLinked(const ArgList &Args) {
> + if (isObjCAutoRefCount(Args))
> + return true;
> + return Args.hasArg(options::OPT_fobjc_link_runtime);
> +}
> +
> static void addProfileRT(const ToolChain &TC, const ArgList &Args,
> ArgStringList &CmdArgs,
> llvm::Triple Triple) {
> @@ -4025,7 +4032,7 @@
> CmdArgs.push_back("-lcrt1.o");
> else if (getDarwinToolChain().isMacosxVersionLT(10, 6))
> CmdArgs.push_back("-lcrt1.10.5.o");
> - else
> + else if (getDarwinToolChain().isMacosxVersionLT(10, 8))
> CmdArgs.push_back("-lcrt1.10.6.o");
>
> // darwin_crt2 spec is empty.
> @@ -4064,14 +4071,24 @@
>
> getDarwinToolChain().AddLinkSearchPathArgs(Args, CmdArgs);
>
> - // In ARC, if we don't have runtime support, link in the runtime
> - // stubs. We have to do this *before* adding any of the normal
> - // linker inputs so that its initializer gets run first.
> - if (isObjCAutoRefCount(Args)) {
> - ObjCRuntime runtime;
> - getDarwinToolChain().configureObjCRuntime(runtime);
> - if (!runtime.HasARC)
> - getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs);
> + if (isObjCRuntimeLinked(Args)) {
> + // Avoid linking compatibility stubs on i386 mac.
> + if (!getDarwinToolChain().isTargetMacOS() ||
> + getDarwinToolChain().getArchName() != "i386") {
> + // If we don't have ARC or subscripting runtime support, link in the
> + // runtime stubs. We have to do this *before* adding any of the normal
> + // linker inputs so that its initializer gets run first.
> + ObjCRuntime runtime;
> + getDarwinToolChain().configureObjCRuntime(runtime);
> + // We use arclite library for both ARC and subscripting support.
> + if ((!runtime.HasARC && isObjCAutoRefCount(Args)) ||
> + !runtime.HasSubscripting)
> + getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs);
> + CmdArgs.push_back("-framework");
> + CmdArgs.push_back("Foundation");
> + }
> + // Link libobj.
> + CmdArgs.push_back("-lobjc");
> }
>
> AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
>
> Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
> +++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Tue Mar 6 14:05:56 2012
> @@ -630,6 +630,10 @@
> .Case("ownership_holds", true)
> .Case("ownership_returns", true)
> .Case("ownership_takes", true)
> + .Case("objc_bool", true)
> + .Case("objc_subscripting", LangOpts.ObjCNonFragileABI)
> + .Case("objc_array_literals", LangOpts.ObjC2)
> + .Case("objc_dictionary_literals", LangOpts.ObjC2)
> .Case("arc_cf_code_audited", true)
> // C11 features
> .Case("c_alignas", LangOpts.C11)
>
> Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseExpr.cpp Tue Mar 6 14:05:56 2012
> @@ -707,6 +707,10 @@
> case tok::kw_true:
> case tok::kw_false:
> return ParseCXXBoolLiteral();
> +
> + case tok::kw___objc_yes:
> + case tok::kw___objc_no:
> + return ParseObjCBoolLiteral();
>
> case tok::kw_nullptr:
> Diag(Tok, diag::warn_cxx98_compat_nullptr);
> @@ -2403,3 +2407,12 @@
> Actions.ActOnBlockError(CaretLoc, getCurScope());
> return move(Result);
> }
> +
> +/// ParseObjCBoolLiteral - This handles the objective-c Boolean literals.
> +///
> +/// '__objc_yes'
> +/// '__objc_no'
> +ExprResult Parser::ParseObjCBoolLiteral() {
> + tok::TokenKind Kind = Tok.getKind();
> + return Actions.ActOnObjCBoolLiteral(ConsumeToken(), Kind);
> +}
>
> Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseObjc.cpp Tue Mar 6 14:05:56 2012
> @@ -2009,11 +2009,64 @@
> cutOffParsing();
> return ExprError();
>
> + case tok::minus:
> + case tok::plus: {
> + tok::TokenKind Kind = Tok.getKind();
> + SourceLocation OpLoc = ConsumeToken();
> +
> + if (!Tok.is(tok::numeric_constant)) {
> + const char *Symbol = 0;
> + switch (Kind) {
> + case tok::minus: Symbol = "-"; break;
> + case tok::plus: Symbol = "+"; break;
> + default: llvm_unreachable("missing unary operator case");
> + }
> + Diag(Tok, diag::err_nsnumber_nonliteral_unary)
> + << Symbol;
> + return ExprError();
> + }
> +
> + ExprResult Lit(Actions.ActOnNumericConstant(Tok));
> + if (Lit.isInvalid()) {
> + return move(Lit);
> + }
> + SourceLocation EndLoc = ConsumeToken(); // consume the literal token.
> +
> + Lit = Actions.ActOnUnaryOp(getCurScope(), OpLoc, Kind, Lit.take());
> + if (Lit.isInvalid())
> + return move(Lit);
> +
> + return ParsePostfixExpressionSuffix(
> + Actions.BuildObjCNumericLiteral(AtLoc, Lit.take()));
> + }
> +
> case tok::string_literal: // primary-expression: string-literal
> case tok::wide_string_literal:
> if (Tok.hasUDSuffix())
> return ExprError(Diag(Tok, diag::err_invalid_string_udl));
> return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
> +
> + case tok::char_constant:
> + return ParsePostfixExpressionSuffix(ParseObjCCharacterLiteral(AtLoc));
> +
> + case tok::numeric_constant:
> + return ParsePostfixExpressionSuffix(ParseObjCNumericLiteral(AtLoc));
> +
> + case tok::kw_true: // Objective-C++, etc.
> + case tok::kw___objc_yes: // c/c++/objc/objc++ __objc_yes
> + return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, true));
> + case tok::kw_false: // Objective-C++, etc.
> + case tok::kw___objc_no: // c/c++/objc/objc++ __objc_no
> + return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, false));
> +
> + case tok::l_square:
> + // Objective-C array literal
> + return ParsePostfixExpressionSuffix(ParseObjCArrayLiteral(AtLoc));
> +
> + case tok::l_brace:
> + // Objective-C dictionary literal
> + return ParsePostfixExpressionSuffix(ParseObjCDictionaryLiteral(AtLoc));
> +
> default:
> if (Tok.getIdentifierInfo() == 0)
> return ExprError(Diag(AtLoc, diag::err_unexpected_at));
> @@ -2491,6 +2544,134 @@
> AtStrings.size()));
> }
>
> +/// ParseObjCBooleanLiteral -
> +/// objc-scalar-literal : '@' boolean-keyword
> +/// ;
> +/// boolean-keyword: 'true' | 'false' | '__objc_yes' | '__objc_no'
> +/// ;
> +ExprResult Parser::ParseObjCBooleanLiteral(SourceLocation AtLoc,
> + bool ArgValue) {
> + SourceLocation EndLoc = ConsumeToken(); // consume the keyword.
> + return Actions.ActOnObjCBoolLiteral(AtLoc, EndLoc, ArgValue);
> +}
> +
> +/// ParseObjCCharacterLiteral -
> +/// objc-scalar-literal : '@' character-literal
> +/// ;
> +ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) {
> + ExprResult Lit(Actions.ActOnCharacterConstant(Tok));
> + if (Lit.isInvalid()) {
> + return move(Lit);
> + }
> + SourceLocation EndLoc = ConsumeToken(); // consume the literal token.
> + return Owned(Actions.BuildObjCNumericLiteral(AtLoc, Lit.take()));
> +}
> +
> +/// ParseObjCNumericLiteral -
> +/// objc-scalar-literal : '@' scalar-literal
> +/// ;
> +/// scalar-literal : | numeric-constant /* any numeric constant. */
> +/// ;
> +ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) {
> + ExprResult Lit(Actions.ActOnNumericConstant(Tok));
> + if (Lit.isInvalid()) {
> + return move(Lit);
> + }
> + SourceLocation EndLoc = ConsumeToken(); // consume the literal token.
> + return Owned(Actions.BuildObjCNumericLiteral(AtLoc, Lit.take()));
> +}
> +
> +ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
> + ExprVector ElementExprs(Actions); // array elements.
> + ConsumeBracket(); // consume the l_square.
> +
> + while (Tok.isNot(tok::r_square)) {
> + // Parse list of array element expressions (all must be id types).
> + ExprResult Res(ParseAssignmentExpression());
> + if (Res.isInvalid()) {
> + // We must manually skip to a ']', otherwise the expression skipper will
> + // stop at the ']' when it skips to the ';'. We want it to skip beyond
> + // the enclosing expression.
> + SkipUntil(tok::r_square);
> + return move(Res);
> + }
> +
> + // Parse the ellipsis that indicates a pack expansion.
> + if (Tok.is(tok::ellipsis))
> + Res = Actions.ActOnPackExpansion(Res.get(), ConsumeToken());
> + if (Res.isInvalid())
> + return true;
> +
> + ElementExprs.push_back(Res.release());
> +
> + if (Tok.is(tok::comma))
> + ConsumeToken(); // Eat the ','.
> + else if (Tok.isNot(tok::r_square))
> + return ExprError(Diag(Tok, diag::err_expected_rsquare_or_comma));
> + }
> + SourceLocation EndLoc = ConsumeBracket(); // location of ']'
> + MultiExprArg Args(Actions, ElementExprs.take(), ElementExprs.size());
> + return Owned(Actions.BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args));
> +}
> +
> +ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
> + SmallVector<ObjCDictionaryElement, 4> Elements; // dictionary elements.
> + ConsumeBrace(); // consume the l_square.
> + while (Tok.isNot(tok::r_brace)) {
> + // Parse the comma separated key : value expressions.
> + ExprResult KeyExpr;
> + {
> + ColonProtectionRAIIObject X(*this);
> + KeyExpr = ParseAssignmentExpression();
> + if (KeyExpr.isInvalid()) {
> + // We must manually skip to a '}', otherwise the expression skipper will
> + // stop at the '}' when it skips to the ';'. We want it to skip beyond
> + // the enclosing expression.
> + SkipUntil(tok::r_brace);
> + return move(KeyExpr);
> + }
> + }
> +
> + if (Tok.is(tok::colon)) {
> + ConsumeToken();
> + } else {
> + return ExprError(Diag(Tok, diag::err_expected_colon));
> + }
> +
> + ExprResult ValueExpr(ParseAssignmentExpression());
> + if (ValueExpr.isInvalid()) {
> + // We must manually skip to a '}', otherwise the expression skipper will
> + // stop at the '}' when it skips to the ';'. We want it to skip beyond
> + // the enclosing expression.
> + SkipUntil(tok::r_brace);
> + return move(ValueExpr);
> + }
> +
> + // Parse the ellipsis that designates this as a pack expansion.
> + SourceLocation EllipsisLoc;
> + if (Tok.is(tok::ellipsis) && getLang().CPlusPlus)
> + EllipsisLoc = ConsumeToken();
> +
> + // We have a valid expression. Collect it in a vector so we can
> + // build the argument list.
> + ObjCDictionaryElement Element = {
> + KeyExpr.get(), ValueExpr.get(), EllipsisLoc, llvm::Optional<unsigned>()
> + };
> + Elements.push_back(Element);
> +
> + if (Tok.is(tok::comma))
> + ConsumeToken(); // Eat the ','.
> + else if (Tok.isNot(tok::r_brace))
> + return ExprError(Diag(Tok, diag::err_expected_rbrace_or_comma));
> + }
> + SourceLocation EndLoc = ConsumeBrace();
> +
> + // Create the ObjCDictionaryLiteral.
> + return Owned(Actions.BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc),
> + Elements.data(),
> + Elements.size()));
> +}
> +
> /// objc-encode-expression:
> /// @encode ( type-name )
> ExprResult
>
> Modified: cfe/trunk/lib/Sema/Sema.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/Sema.cpp (original)
> +++ cfe/trunk/lib/Sema/Sema.cpp Tue Mar 6 14:05:56 2012
> @@ -90,6 +90,8 @@
> PackContext(0), MSStructPragmaOn(false), VisContext(0),
> ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0),
> IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
> + NSNumberDecl(0), NSArrayDecl(0), ArrayWithObjectsMethod(0),
> + NSDictionaryDecl(0), DictionaryWithObjectsMethod(0),
> GlobalNewDeleteDeclared(false),
> ObjCShouldCallSuperDealloc(false),
> ObjCShouldCallSuperFinalize(false),
> @@ -102,7 +104,12 @@
> {
> TUScope = 0;
> LoadedExternalKnownNamespaces = false;
> -
> + for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I)
> + NSNumberLiteralMethods[I] = 0;
> +
> + if (getLangOptions().ObjC1)
> + NSAPIObj.reset(new NSAPI(Context));
> +
> if (getLangOptions().CPlusPlus)
> FieldCollector.reset(new CXXFieldCollector());
>
>
> Modified: cfe/trunk/lib/Sema/SemaCast.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCast.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaCast.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaCast.cpp Tue Mar 6 14:05:56 2012
> @@ -1528,6 +1528,8 @@
> case OK_BitField: inappropriate = "bit-field"; break;
> case OK_VectorComponent: inappropriate = "vector element"; break;
> case OK_ObjCProperty: inappropriate = "property expression"; break;
> + case OK_ObjCSubscript: inappropriate = "container subscripting expression";
> + break;
> }
> if (inappropriate) {
> Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_reference)
>
> Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Tue Mar 6 14:05:56 2012
> @@ -4392,6 +4392,26 @@
> Builder.AddPlaceholderChunk("selector");
> Builder.AddChunk(CodeCompletionString::CK_RightParen);
> Results.AddResult(Result(Builder.TakeString()));
> +
> + // @[ objects, ... ]
> + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,[));
> + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
> + Builder.AddPlaceholderChunk("objects, ...");
> + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
> + Builder.AddChunk(CodeCompletionString::CK_RightBracket);
> + Results.AddResult(Result(Builder.TakeString()));
> +
> + // @{ key : object, ... }
> + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,{));
> + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
> + Builder.AddPlaceholderChunk("key");
> + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
> + Builder.AddChunk(CodeCompletionString::CK_Colon);
> + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
> + Builder.AddPlaceholderChunk("object, ...");
> + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
> + Builder.AddChunk(CodeCompletionString::CK_RightBrace);
> + Results.AddResult(Result(Builder.TakeString()));
> }
>
> static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Mar 6 14:05:56 2012
> @@ -2390,14 +2390,18 @@
> Tok.getLocation()));
> }
>
> +ExprResult Sema::ActOnIntegerConstant(SourceLocation Loc, uint64_t Val) {
> + unsigned IntSize = Context.getTargetInfo().getIntWidth();
> + return Owned(IntegerLiteral::Create(Context, llvm::APInt(IntSize, Val),
> + Context.IntTy, Loc));
> +}
> +
> ExprResult Sema::ActOnNumericConstant(const Token &Tok) {
> // Fast path for a single digit (which is quite common). A single digit
> // cannot have a trigraph, escaped newline, radix prefix, or type suffix.
> if (Tok.getLength() == 1) {
> const char Val = PP.getSpellingOfSingleCharacterNumericConstant(Tok);
> - unsigned IntSize = Context.getTargetInfo().getIntWidth();
> - return Owned(IntegerLiteral::Create(Context, llvm::APInt(IntSize, Val-'0'),
> - Context.IntTy, Tok.getLocation()));
> + return ActOnIntegerConstant(Tok.getLocation(), Val-'0');
> }
>
> SmallString<512> IntegerBuffer;
> @@ -2926,7 +2930,8 @@
> (LHSExp->getType()->isRecordType() ||
> LHSExp->getType()->isEnumeralType() ||
> RHSExp->getType()->isRecordType() ||
> - RHSExp->getType()->isEnumeralType())) {
> + RHSExp->getType()->isEnumeralType()) &&
> + !LHSExp->getType()->isObjCObjectPointerType()) {
> return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, Base, Idx);
> }
>
> @@ -2979,6 +2984,9 @@
> LHSTy->getAs<ObjCObjectPointerType>()) {
> BaseExpr = LHSExp;
> IndexExpr = RHSExp;
> + Result = BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, 0, 0);
> + if (!Result.isInvalid())
> + return Owned(Result.take());
> ResultType = PTy->getPointeeType();
> } else if (const ObjCObjectPointerType *PTy =
> RHSTy->getAs<ObjCObjectPointerType>()) {
> @@ -11001,3 +11009,12 @@
> return E->getType()->isIntegralOrEnumerationType();
> return false;
> }
> +
> +/// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.
> +ExprResult
> +Sema::ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
> + assert((Kind == tok::kw___objc_yes || Kind == tok::kw___objc_no) &&
> + "Unknown Objective-C Boolean value!");
> + return Owned(new (Context) ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes,
> + Context.ObjCBuiltinBoolTy, OpLoc));
> +}
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Mar 6 14:05:56 2012
> @@ -4456,11 +4456,27 @@
> } else if (isa<StmtExpr>(E)) {
> ReturnsRetained = true;
>
> + // We hit this case with the lambda conversion-to-block optimization;
> + // we don't want any extra casts here.
> + } else if (isa<CastExpr>(E) &&
> + isa<BlockExpr>(cast<CastExpr>(E)->getSubExpr())) {
> + return Owned(E);
> +
> // For message sends and property references, we try to find an
> // actual method. FIXME: we should infer retention by selector in
> // cases where we don't have an actual method.
> - } else if (ObjCMessageExpr *Send = dyn_cast<ObjCMessageExpr>(E)) {
> - ObjCMethodDecl *D = Send->getMethodDecl();
> + } else {
> + ObjCMethodDecl *D = 0;
> + if (ObjCMessageExpr *Send = dyn_cast<ObjCMessageExpr>(E)) {
> + D = Send->getMethodDecl();
> + } else if (ObjCNumericLiteral *NumLit = dyn_cast<ObjCNumericLiteral>(E)) {
> + D = NumLit->getObjCNumericLiteralMethod();
> + } else if (ObjCArrayLiteral *ArrayLit = dyn_cast<ObjCArrayLiteral>(E)) {
> + D = ArrayLit->getArrayWithObjectsMethod();
> + } else if (ObjCDictionaryLiteral *DictLit
> + = dyn_cast<ObjCDictionaryLiteral>(E)) {
> + D = DictLit->getDictWithObjectsMethod();
> + }
>
> ReturnsRetained = (D && D->hasAttr<NSReturnsRetainedAttr>());
>
> @@ -4470,13 +4486,6 @@
> if (!ReturnsRetained &&
> D && D->getMethodFamily() == OMF_performSelector)
> return Owned(E);
> - } else if (isa<CastExpr>(E) &&
> - isa<BlockExpr>(cast<CastExpr>(E)->getSubExpr())) {
> - // We hit this case with the lambda conversion-to-block optimization;
> - // we don't want any extra casts here.
> - return Owned(E);
> - } else {
> - ReturnsRetained = false;
> }
>
> // Don't reclaim an object of Class type.
>
> Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Mar 6 14:05:56 2012
> @@ -17,6 +17,8 @@
> #include "clang/Sema/ScopeInfo.h"
> #include "clang/Sema/Initialization.h"
> #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
> +#include "clang/Edit/Rewriters.h"
> +#include "clang/Edit/Commit.h"
> #include "clang/AST/ASTContext.h"
> #include "clang/AST/DeclObjC.h"
> #include "clang/AST/ExprObjC.h"
> @@ -70,7 +72,11 @@
> Context.getPointerType(Context.CharTy),
> &StrLocs[0], StrLocs.size());
> }
> +
> + return BuildObjCStringLiteral(AtLocs[0], S);
> +}
>
> +ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){
> // Verify that this composite string is acceptable for ObjC strings.
> if (CheckObjCString(S))
> return true;
> @@ -91,7 +97,7 @@
> else
> NSIdent = &Context.Idents.get(StringClass);
>
> - NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLocs[0],
> + NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc,
> LookupOrdinaryName);
> if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
> Context.setObjCConstantStringInterface(StrIF);
> @@ -106,7 +112,7 @@
> }
> } else {
> IdentifierInfo *NSIdent = &Context.Idents.get("NSString");
> - NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLocs[0],
> + NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc,
> LookupOrdinaryName);
> if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
> Context.setObjCConstantStringInterface(StrIF);
> @@ -131,7 +137,613 @@
> }
> }
>
> - return new (Context) ObjCStringLiteral(S, Ty, AtLocs[0]);
> + return new (Context) ObjCStringLiteral(S, Ty, AtLoc);
> +}
> +
> +/// \brief Retrieve the NSNumber factory method that should be used to create
> +/// an Objective-C literal for the given type.
> +static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
> + QualType T, QualType ReturnType,
> + SourceRange Range) {
> + llvm::Optional<NSAPI::NSNumberLiteralMethodKind> Kind
> + = S.NSAPIObj->getNSNumberFactoryMethodKind(T);
> +
> + if (!Kind) {
> + S.Diag(Loc, diag::err_invalid_nsnumber_type)
> + << T << Range;
> + return 0;
> + }
> +
> + // If we already looked up this method, we're done.
> + if (S.NSNumberLiteralMethods[*Kind])
> + return S.NSNumberLiteralMethods[*Kind];
> +
> + Selector Sel = S.NSAPIObj->getNSNumberLiteralSelector(*Kind,
> + /*Instance=*/false);
> +
> + // Look for the appropriate method within NSNumber.
> + ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel);;
> + if (!Method && S.getLangOptions().DebuggerObjCLiteral) {
> + TypeSourceInfo *ResultTInfo = 0;
> + Method = ObjCMethodDecl::Create(S.Context, SourceLocation(), SourceLocation(), Sel,
> + ReturnType,
> + ResultTInfo,
> + S.Context.getTranslationUnitDecl(),
> + false /*Instance*/, false/*isVariadic*/,
> + /*isSynthesized=*/false,
> + /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
> + ObjCMethodDecl::Required,
> + false);
> + ParmVarDecl *value = ParmVarDecl::Create(S.Context, Method,
> + SourceLocation(), SourceLocation(),
> + &S.Context.Idents.get("value"),
> + T, /*TInfo=*/0, SC_None, SC_None, 0);
> + Method->setMethodParams(S.Context, value, ArrayRef<SourceLocation>());
> + }
> +
> + if (!Method) {
> + S.Diag(Loc, diag::err_undeclared_nsnumber_method) << Sel;
> + return 0;
> + }
> +
> + // Make sure the return type is reasonable.
> + if (!Method->getResultType()->isObjCObjectPointerType()) {
> + S.Diag(Loc, diag::err_objc_literal_method_sig)
> + << Sel;
> + S.Diag(Method->getLocation(), diag::note_objc_literal_method_return)
> + << Method->getResultType();
> + return 0;
> + }
> +
> + // Note: if the parameter type is out-of-line, we'll catch it later in the
> + // implicit conversion.
> +
> + S.NSNumberLiteralMethods[*Kind] = Method;
> + return Method;
> +}
> +
> +/// BuildObjCNumericLiteral - builds an ObjCNumericLiteral AST node for the
> +/// numeric literal expression. Type of the expression will be "NSNumber *"
> +/// or "id" if NSNumber is unavailable.
> +ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) {
> + // Look up the NSNumber class, if we haven't done so already.
> + if (!NSNumberDecl) {
> + NamedDecl *IF = LookupSingleName(TUScope,
> + NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber),
> + AtLoc, LookupOrdinaryName);
> + NSNumberDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
> +
> + if (!NSNumberDecl && getLangOptions().DebuggerObjCLiteral)
> + NSNumberDecl = ObjCInterfaceDecl::Create (Context,
> + Context.getTranslationUnitDecl(),
> + SourceLocation(),
> + NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber),
> + 0, SourceLocation());
> + if (!NSNumberDecl) {
> + Diag(AtLoc, diag::err_undeclared_nsnumber);
> + return ExprError();
> + }
> + }
> +
> + // Determine the type of the literal.
> + QualType NumberType = Number->getType();
> + if (CharacterLiteral *Char = dyn_cast<CharacterLiteral>(Number)) {
> + // In C, character literals have type 'int'. That's not the type we want
> + // to use to determine the Objective-c literal kind.
> + switch (Char->getKind()) {
> + case CharacterLiteral::Ascii:
> + NumberType = Context.CharTy;
> + break;
> +
> + case CharacterLiteral::Wide:
> + NumberType = Context.getWCharType();
> + break;
> +
> + case CharacterLiteral::UTF16:
> + NumberType = Context.Char16Ty;
> + break;
> +
> + case CharacterLiteral::UTF32:
> + NumberType = Context.Char32Ty;
> + break;
> + }
> + }
> +
> + ObjCMethodDecl *Method = 0;
> + // Look for the appropriate method within NSNumber.
> + // Construct the literal.
> + QualType Ty
> + = Context.getObjCObjectPointerType(
> + Context.getObjCInterfaceType(NSNumberDecl));
> + Method = getNSNumberFactoryMethod(*this, AtLoc,
> + NumberType, Ty,
> + Number->getSourceRange());
> +
> + if (!Method)
> + return ExprError();
> +
> + // Convert the number to the type that the parameter expects.
> + QualType ElementT = Method->param_begin()[0]->getType();
> + ExprResult ConvertedNumber = PerformImplicitConversion(Number, ElementT,
> + AA_Sending);
> + if (ConvertedNumber.isInvalid())
> + return ExprError();
> + Number = ConvertedNumber.get();
> +
> + return MaybeBindToTemporary(
> + new (Context) ObjCNumericLiteral(Number, Ty, Method, AtLoc));
> +}
> +
> +ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc,
> + SourceLocation ValueLoc,
> + bool Value) {
> + ExprResult Inner;
> + if (getLangOptions().CPlusPlus) {
> + Inner = ActOnCXXBoolLiteral(ValueLoc, Value? tok::kw_true : tok::kw_false);
> + } else {
> + // C doesn't actually have a way to represent literal values of type
> + // _Bool. So, we'll use 0/1 and implicit cast to _Bool.
> + Inner = ActOnIntegerConstant(ValueLoc, Value? 1 : 0);
> + Inner = ImpCastExprToType(Inner.get(), Context.BoolTy,
> + CK_IntegralToBoolean);
> + }
> +
> + return BuildObjCNumericLiteral(AtLoc, Inner.get());
> +}
> +
> +/// \brief Check that the given expression is a valid element of an Objective-C
> +/// collection literal.
> +static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
> + QualType T) {
> + // If the expression is type-dependent, there's nothing for us to do.
> + if (Element->isTypeDependent())
> + return Element;
> +
> + ExprResult Result = S.CheckPlaceholderExpr(Element);
> + if (Result.isInvalid())
> + return ExprError();
> + Element = Result.get();
> +
> + // In C++, check for an implicit conversion to an Objective-C object pointer
> + // type.
> + if (S.getLangOptions().CPlusPlus && Element->getType()->isRecordType()) {
> + InitializedEntity Entity
> + = InitializedEntity::InitializeParameter(S.Context, T, /*Consumed=*/false);
> + InitializationKind Kind
> + = InitializationKind::CreateCopy(Element->getLocStart(), SourceLocation());
> + InitializationSequence Seq(S, Entity, Kind, &Element, 1);
> + if (!Seq.Failed())
> + return Seq.Perform(S, Entity, Kind, MultiExprArg(S, &Element, 1));
> + }
> +
> + Expr *OrigElement = Element;
> +
> + // Perform lvalue-to-rvalue conversion.
> + Result = S.DefaultLvalueConversion(Element);
> + if (Result.isInvalid())
> + return ExprError();
> + Element = Result.get();
> +
> + // Make sure that we have an Objective-C pointer type or block.
> + if (!Element->getType()->isObjCObjectPointerType() &&
> + !Element->getType()->isBlockPointerType()) {
> + bool Recovered = false;
> +
> + // If this is potentially an Objective-C numeric literal, add the '@'.
> + if (isa<IntegerLiteral>(OrigElement) ||
> + isa<CharacterLiteral>(OrigElement) ||
> + isa<FloatingLiteral>(OrigElement) ||
> + isa<ObjCBoolLiteralExpr>(OrigElement) ||
> + isa<CXXBoolLiteralExpr>(OrigElement)) {
> + if (S.NSAPIObj->getNSNumberFactoryMethodKind(OrigElement->getType())) {
> + int Which = isa<CharacterLiteral>(OrigElement) ? 1
> + : (isa<CXXBoolLiteralExpr>(OrigElement) ||
> + isa<ObjCBoolLiteralExpr>(OrigElement)) ? 2
> + : 3;
> +
> + S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection)
> + << Which << OrigElement->getSourceRange()
> + << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@");
> +
> + Result = S.BuildObjCNumericLiteral(OrigElement->getLocStart(),
> + OrigElement);
> + if (Result.isInvalid())
> + return ExprError();
> +
> + Element = Result.get();
> + Recovered = true;
> + }
> + }
> + // If this is potentially an Objective-C string literal, add the '@'.
> + else if (StringLiteral *String = dyn_cast<StringLiteral>(OrigElement)) {
> + if (String->isAscii()) {
> + S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection)
> + << 0 << OrigElement->getSourceRange()
> + << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@");
> +
> + Result = S.BuildObjCStringLiteral(OrigElement->getLocStart(), String);
> + if (Result.isInvalid())
> + return ExprError();
> +
> + Element = Result.get();
> + Recovered = true;
> + }
> + }
> +
> + if (!Recovered) {
> + S.Diag(Element->getLocStart(), diag::err_invalid_collection_element)
> + << Element->getType();
> + return ExprError();
> + }
> + }
> +
> + // Make sure that the element has the type that the container factory
> + // function expects.
> + return S.PerformCopyInitialization(
> + InitializedEntity::InitializeParameter(S.Context, T,
> + /*Consumed=*/false),
> + Element->getLocStart(), Element);
> +}
> +
> +ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
> + Expr *IndexExpr,
> + ObjCMethodDecl *getterMethod,
> + ObjCMethodDecl *setterMethod) {
> + // Feature support is for modern abi.
> + if (!LangOpts.ObjCNonFragileABI)
> + return ExprError();
> + // If the expression is type-dependent, there's nothing for us to do.
> + assert ((!BaseExpr->isTypeDependent() && !IndexExpr->isTypeDependent()) &&
> + "base or index cannot have dependent type here");
> + ExprResult Result = CheckPlaceholderExpr(IndexExpr);
> + if (Result.isInvalid())
> + return ExprError();
> + IndexExpr = Result.get();
> +
> + // Perform lvalue-to-rvalue conversion.
> + Result = DefaultLvalueConversion(BaseExpr);
> + if (Result.isInvalid())
> + return ExprError();
> + BaseExpr = Result.get();
> + return Owned(ObjCSubscriptRefExpr::Create(Context,
> + BaseExpr,
> + IndexExpr,
> + Context.PseudoObjectTy,
> + getterMethod,
> + setterMethod, RB));
> +
> +}
> +
> +ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
> + // Look up the NSArray class, if we haven't done so already.
> + if (!NSArrayDecl) {
> + NamedDecl *IF = LookupSingleName(TUScope,
> + NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
> + SR.getBegin(),
> + LookupOrdinaryName);
> + NSArrayDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
> + if (!NSArrayDecl && getLangOptions().DebuggerObjCLiteral)
> + NSArrayDecl = ObjCInterfaceDecl::Create (Context,
> + Context.getTranslationUnitDecl(),
> + SourceLocation(),
> + NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
> + 0, SourceLocation());
> +
> + if (!NSArrayDecl) {
> + Diag(SR.getBegin(), diag::err_undeclared_nsarray);
> + return ExprError();
> + }
> + }
> +
> + // Find the arrayWithObjects:count: method, if we haven't done so already.
> + QualType IdT = Context.getObjCIdType();
> + if (!ArrayWithObjectsMethod) {
> + Selector
> + Sel = NSAPIObj->getNSArraySelector(NSAPI::NSArr_arrayWithObjectsCount);
> + ArrayWithObjectsMethod = NSArrayDecl->lookupClassMethod(Sel);
> + if (!ArrayWithObjectsMethod && getLangOptions().DebuggerObjCLiteral) {
> + TypeSourceInfo *ResultTInfo = 0;
> + ArrayWithObjectsMethod =
> + ObjCMethodDecl::Create(Context,
> + SourceLocation(), SourceLocation(), Sel,
> + IdT,
> + ResultTInfo,
> + Context.getTranslationUnitDecl(),
> + false /*Instance*/, false/*isVariadic*/,
> + /*isSynthesized=*/false,
> + /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
> + ObjCMethodDecl::Required,
> + false);
> + SmallVector<ParmVarDecl *, 2> Params;
> + ParmVarDecl *objects = ParmVarDecl::Create(Context, ArrayWithObjectsMethod,
> + SourceLocation(), SourceLocation(),
> + &Context.Idents.get("objects"),
> + Context.getPointerType(IdT),
> + /*TInfo=*/0,
> + SC_None,
> + SC_None,
> + 0);
> + Params.push_back(objects);
> + ParmVarDecl *cnt = ParmVarDecl::Create(Context, ArrayWithObjectsMethod,
> + SourceLocation(), SourceLocation(),
> + &Context.Idents.get("cnt"),
> + Context.UnsignedLongTy,
> + /*TInfo=*/0,
> + SC_None,
> + SC_None,
> + 0);
> + Params.push_back(cnt);
> + ArrayWithObjectsMethod->setMethodParams(Context, Params,
> + ArrayRef<SourceLocation>());
> +
> +
> + }
> +
> + if (!ArrayWithObjectsMethod) {
> + Diag(SR.getBegin(), diag::err_undeclared_arraywithobjects) << Sel;
> + return ExprError();
> + }
> + }
> +
> + // Make sure the return type is reasonable.
> + if (!ArrayWithObjectsMethod->getResultType()->isObjCObjectPointerType()) {
> + Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
> + << ArrayWithObjectsMethod->getSelector();
> + Diag(ArrayWithObjectsMethod->getLocation(),
> + diag::note_objc_literal_method_return)
> + << ArrayWithObjectsMethod->getResultType();
> + return ExprError();
> + }
> +
> + // Dig out the type that all elements should be converted to.
> + QualType T = ArrayWithObjectsMethod->param_begin()[0]->getType();
> + const PointerType *PtrT = T->getAs<PointerType>();
> + if (!PtrT ||
> + !Context.hasSameUnqualifiedType(PtrT->getPointeeType(), IdT)) {
> + Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
> + << ArrayWithObjectsMethod->getSelector();
> + Diag(ArrayWithObjectsMethod->param_begin()[0]->getLocation(),
> + diag::note_objc_literal_method_param)
> + << 0 << T
> + << Context.getPointerType(IdT.withConst());
> + return ExprError();
> + }
> + T = PtrT->getPointeeType();
> +
> + // Check that the 'count' parameter is integral.
> + if (!ArrayWithObjectsMethod->param_begin()[1]->getType()->isIntegerType()) {
> + Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
> + << ArrayWithObjectsMethod->getSelector();
> + Diag(ArrayWithObjectsMethod->param_begin()[1]->getLocation(),
> + diag::note_objc_literal_method_param)
> + << 1
> + << ArrayWithObjectsMethod->param_begin()[1]->getType()
> + << "integral";
> + return ExprError();
> + }
> +
> + // Check that each of the elements provided is valid in a collection literal,
> + // performing conversions as necessary.
> + Expr **ElementsBuffer = Elements.get();
> + for (unsigned I = 0, N = Elements.size(); I != N; ++I) {
> + ExprResult Converted = CheckObjCCollectionLiteralElement(*this,
> + ElementsBuffer[I],
> + T);
> + if (Converted.isInvalid())
> + return ExprError();
> +
> + ElementsBuffer[I] = Converted.get();
> + }
> +
> + QualType Ty
> + = Context.getObjCObjectPointerType(
> + Context.getObjCInterfaceType(NSArrayDecl));
> +
> + return MaybeBindToTemporary(
> + ObjCArrayLiteral::Create(Context,
> + llvm::makeArrayRef(Elements.get(),
> + Elements.size()),
> + Ty, ArrayWithObjectsMethod, SR));
> +}
> +
> +ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
> + ObjCDictionaryElement *Elements,
> + unsigned NumElements) {
> + // Look up the NSDictionary class, if we haven't done so already.
> + if (!NSDictionaryDecl) {
> + NamedDecl *IF = LookupSingleName(TUScope,
> + NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
> + SR.getBegin(), LookupOrdinaryName);
> + NSDictionaryDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
> + if (!NSDictionaryDecl && getLangOptions().DebuggerObjCLiteral)
> + NSDictionaryDecl = ObjCInterfaceDecl::Create (Context,
> + Context.getTranslationUnitDecl(),
> + SourceLocation(),
> + NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
> + 0, SourceLocation());
> +
> + if (!NSDictionaryDecl) {
> + Diag(SR.getBegin(), diag::err_undeclared_nsdictionary);
> + return ExprError();
> + }
> + }
> +
> + // Find the dictionaryWithObjects:forKeys:count: method, if we haven't done
> + // so already.
> + QualType IdT = Context.getObjCIdType();
> + if (!DictionaryWithObjectsMethod) {
> + Selector Sel = NSAPIObj->getNSDictionarySelector(
> + NSAPI::NSDict_dictionaryWithObjectsForKeysCount);
> + DictionaryWithObjectsMethod = NSDictionaryDecl->lookupClassMethod(Sel);
> + if (!DictionaryWithObjectsMethod && getLangOptions().DebuggerObjCLiteral) {
> + DictionaryWithObjectsMethod =
> + ObjCMethodDecl::Create(Context,
> + SourceLocation(), SourceLocation(), Sel,
> + IdT,
> + 0 /*TypeSourceInfo */,
> + Context.getTranslationUnitDecl(),
> + false /*Instance*/, false/*isVariadic*/,
> + /*isSynthesized=*/false,
> + /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
> + ObjCMethodDecl::Required,
> + false);
> + SmallVector<ParmVarDecl *, 3> Params;
> + ParmVarDecl *objects = ParmVarDecl::Create(Context, DictionaryWithObjectsMethod,
> + SourceLocation(), SourceLocation(),
> + &Context.Idents.get("objects"),
> + Context.getPointerType(IdT),
> + /*TInfo=*/0,
> + SC_None,
> + SC_None,
> + 0);
> + Params.push_back(objects);
> + ParmVarDecl *keys = ParmVarDecl::Create(Context, DictionaryWithObjectsMethod,
> + SourceLocation(), SourceLocation(),
> + &Context.Idents.get("keys"),
> + Context.getPointerType(IdT),
> + /*TInfo=*/0,
> + SC_None,
> + SC_None,
> + 0);
> + Params.push_back(keys);
> + ParmVarDecl *cnt = ParmVarDecl::Create(Context, DictionaryWithObjectsMethod,
> + SourceLocation(), SourceLocation(),
> + &Context.Idents.get("cnt"),
> + Context.UnsignedLongTy,
> + /*TInfo=*/0,
> + SC_None,
> + SC_None,
> + 0);
> + Params.push_back(cnt);
> + DictionaryWithObjectsMethod->setMethodParams(Context, Params,
> + ArrayRef<SourceLocation>());
> + }
> +
> + if (!DictionaryWithObjectsMethod) {
> + Diag(SR.getBegin(), diag::err_undeclared_dictwithobjects) << Sel;
> + return ExprError();
> + }
> + }
> +
> + // Make sure the return type is reasonable.
> + if (!DictionaryWithObjectsMethod->getResultType()->isObjCObjectPointerType()){
> + Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
> + << DictionaryWithObjectsMethod->getSelector();
> + Diag(DictionaryWithObjectsMethod->getLocation(),
> + diag::note_objc_literal_method_return)
> + << DictionaryWithObjectsMethod->getResultType();
> + return ExprError();
> + }
> +
> + // Dig out the type that all values should be converted to.
> + QualType ValueT = DictionaryWithObjectsMethod->param_begin()[0]->getType();
> + const PointerType *PtrValue = ValueT->getAs<PointerType>();
> + if (!PtrValue ||
> + !Context.hasSameUnqualifiedType(PtrValue->getPointeeType(), IdT)) {
> + Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
> + << DictionaryWithObjectsMethod->getSelector();
> + Diag(DictionaryWithObjectsMethod->param_begin()[0]->getLocation(),
> + diag::note_objc_literal_method_param)
> + << 0 << ValueT
> + << Context.getPointerType(IdT.withConst());
> + return ExprError();
> + }
> + ValueT = PtrValue->getPointeeType();
> +
> + // Dig out the type that all keys should be converted to.
> + QualType KeyT = DictionaryWithObjectsMethod->param_begin()[1]->getType();
> + const PointerType *PtrKey = KeyT->getAs<PointerType>();
> + if (!PtrKey ||
> + !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),
> + IdT)) {
> + bool err = true;
> + if (PtrKey) {
> + if (QIDNSCopying.isNull()) {
> + // key argument of selector is id<NSCopying>?
> + if (ObjCProtocolDecl *NSCopyingPDecl =
> + LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) {
> + ObjCProtocolDecl *PQ[] = {NSCopyingPDecl};
> + QIDNSCopying =
> + Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
> + (ObjCProtocolDecl**) PQ,1);
> + QIDNSCopying = Context.getObjCObjectPointerType(QIDNSCopying);
> + }
> + }
> + if (!QIDNSCopying.isNull())
> + err = !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),
> + QIDNSCopying);
> + }
> +
> + if (err) {
> + Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
> + << DictionaryWithObjectsMethod->getSelector();
> + Diag(DictionaryWithObjectsMethod->param_begin()[1]->getLocation(),
> + diag::note_objc_literal_method_param)
> + << 1 << KeyT
> + << Context.getPointerType(IdT.withConst());
> + return ExprError();
> + }
> + }
> + KeyT = PtrKey->getPointeeType();
> +
> + // Check that the 'count' parameter is integral.
> + if (!DictionaryWithObjectsMethod->param_begin()[2]->getType()
> + ->isIntegerType()) {
> + Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
> + << DictionaryWithObjectsMethod->getSelector();
> + Diag(DictionaryWithObjectsMethod->param_begin()[2]->getLocation(),
> + diag::note_objc_literal_method_param)
> + << 2
> + << DictionaryWithObjectsMethod->param_begin()[2]->getType()
> + << "integral";
> + return ExprError();
> + }
> +
> + // Check that each of the keys and values provided is valid in a collection
> + // literal, performing conversions as necessary.
> + bool HasPackExpansions = false;
> + for (unsigned I = 0, N = NumElements; I != N; ++I) {
> + // Check the key.
> + ExprResult Key = CheckObjCCollectionLiteralElement(*this, Elements[I].Key,
> + KeyT);
> + if (Key.isInvalid())
> + return ExprError();
> +
> + // Check the value.
> + ExprResult Value
> + = CheckObjCCollectionLiteralElement(*this, Elements[I].Value, ValueT);
> + if (Value.isInvalid())
> + return ExprError();
> +
> + Elements[I].Key = Key.get();
> + Elements[I].Value = Value.get();
> +
> + if (Elements[I].EllipsisLoc.isInvalid())
> + continue;
> +
> + if (!Elements[I].Key->containsUnexpandedParameterPack() &&
> + !Elements[I].Value->containsUnexpandedParameterPack()) {
> + Diag(Elements[I].EllipsisLoc,
> + diag::err_pack_expansion_without_parameter_packs)
> + << SourceRange(Elements[I].Key->getLocStart(),
> + Elements[I].Value->getLocEnd());
> + return ExprError();
> + }
> +
> + HasPackExpansions = true;
> + }
> +
> +
> + QualType Ty
> + = Context.getObjCObjectPointerType(
> + Context.getObjCInterfaceType(NSDictionaryDecl));
> + return MaybeBindToTemporary(
> + ObjCDictionaryLiteral::Create(Context,
> + llvm::makeArrayRef(Elements,
> + NumElements),
> + HasPackExpansions,
> + Ty,
> + DictionaryWithObjectsMethod, SR));
> }
>
> ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
> @@ -1030,6 +1642,50 @@
>
> }
>
> +static void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg,
> + unsigned DiagID,
> + bool (*refactor)(const ObjCMessageExpr *,
> + const NSAPI &, edit::Commit &)) {
> + SourceLocation MsgLoc = Msg->getExprLoc();
> + if (S.Diags.getDiagnosticLevel(DiagID, MsgLoc) == DiagnosticsEngine::Ignored)
> + return;
> +
> + SourceManager &SM = S.SourceMgr;
> + edit::Commit ECommit(SM, S.LangOpts);
> + if (refactor(Msg,*S.NSAPIObj, ECommit)) {
> + DiagnosticBuilder Builder = S.Diag(MsgLoc, DiagID)
> + << Msg->getSelector() << Msg->getSourceRange();
> + // FIXME: Don't emit diagnostic at all if fixits are non-commitable.
> + if (!ECommit.isCommitable())
> + return;
> + for (edit::Commit::edit_iterator
> + I = ECommit.edit_begin(), E = ECommit.edit_end(); I != E; ++I) {
> + const edit::Commit::Edit &Edit = *I;
> + switch (Edit.Kind) {
> + case edit::Commit::Act_Insert:
> + Builder.AddFixItHint(FixItHint::CreateInsertion(Edit.OrigLoc,
> + Edit.Text,
> + Edit.BeforePrev));
> + break;
> + case edit::Commit::Act_InsertFromRange:
> + Builder.AddFixItHint(
> + FixItHint::CreateInsertionFromRange(Edit.OrigLoc,
> + Edit.getInsertFromRange(SM),
> + Edit.BeforePrev));
> + break;
> + case edit::Commit::Act_Remove:
> + Builder.AddFixItHint(FixItHint::CreateRemoval(Edit.getFileRange(SM)));
> + break;
> + }
> + }
> + }
> +}
> +
> +static void checkCocoaAPI(Sema &S, const ObjCMessageExpr *Msg) {
> + applyCocoaAPICheck(S, Msg, diag::warn_objc_redundant_literal_use,
> + edit::rewriteObjCRedundantCallWithLiteral);
> +}
> +
> /// \brief Build an Objective-C class message expression.
> ///
> /// This routine takes care of both normal class messages and
> @@ -1146,18 +1802,21 @@
> return ExprError();
>
> // Construct the appropriate ObjCMessageExpr.
> - Expr *Result;
> + ObjCMessageExpr *Result;
> if (SuperLoc.isValid())
> Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
> SuperLoc, /*IsInstanceSuper=*/false,
> ReceiverType, Sel, SelectorLocs,
> Method, makeArrayRef(Args, NumArgs),
> RBracLoc, isImplicit);
> - else
> + else {
> Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
> ReceiverTypeInfo, Sel, SelectorLocs,
> Method, makeArrayRef(Args, NumArgs),
> RBracLoc, isImplicit);
> + if (!isImplicit)
> + checkCocoaAPI(*this, Result);
> + }
> return MaybeBindToTemporary(Result);
> }
>
> @@ -1563,11 +2222,14 @@
> ReceiverType, Sel, SelectorLocs, Method,
> makeArrayRef(Args, NumArgs), RBracLoc,
> isImplicit);
> - else
> + else {
> Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
> Receiver, Sel, SelectorLocs, Method,
> makeArrayRef(Args, NumArgs), RBracLoc,
> isImplicit);
> + if (!isImplicit)
> + checkCocoaAPI(*this, Result);
> + }
>
> if (getLangOptions().ObjCAutoRefCount) {
> // In ARC, annotate delegate init calls.
>
> Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Tue Mar 6 14:05:56 2012
> @@ -130,6 +130,28 @@
> }
> };
>
> + struct ObjCSubscriptRefRebuilder : Rebuilder<ObjCSubscriptRefRebuilder> {
> + Expr *NewBase;
> + Expr *NewKeyExpr;
> + ObjCSubscriptRefRebuilder(Sema &S, Expr *newBase, Expr *newKeyExpr)
> + : Rebuilder<ObjCSubscriptRefRebuilder>(S),
> + NewBase(newBase), NewKeyExpr(newKeyExpr) {}
> +
> + typedef ObjCSubscriptRefExpr specific_type;
> + Expr *rebuildSpecific(ObjCSubscriptRefExpr *refExpr) {
> + assert(refExpr->getBaseExpr());
> + assert(refExpr->getKeyExpr());
> +
> + return new (S.Context)
> + ObjCSubscriptRefExpr(NewBase,
> + NewKeyExpr,
> + refExpr->getType(), refExpr->getValueKind(),
> + refExpr->getObjectKind(),refExpr->getAtIndexMethodDecl(),
> + refExpr->setAtIndexMethodDecl(),
> + refExpr->getRBracket());
> + }
> + };
> +
> class PseudoOpBuilder {
> public:
> Sema &S;
> @@ -215,6 +237,39 @@
> ExprResult buildGet();
> ExprResult buildSet(Expr *op, SourceLocation, bool);
> };
> +
> + /// A PseudoOpBuilder for Objective-C array/dictionary indexing.
> + class ObjCSubscriptOpBuilder : public PseudoOpBuilder {
> + ObjCSubscriptRefExpr *RefExpr;
> + OpaqueValueExpr *InstanceBase;
> + OpaqueValueExpr *InstanceKey;
> + ObjCMethodDecl *AtIndexGetter;
> + Selector AtIndexGetterSelector;
> +
> + ObjCMethodDecl *AtIndexSetter;
> + Selector AtIndexSetterSelector;
> +
> + public:
> + ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) :
> + PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
> + RefExpr(refExpr),
> + InstanceBase(0), InstanceKey(0),
> + AtIndexGetter(0), AtIndexSetter(0) { }
> +
> + ExprResult buildRValueOperation(Expr *op);
> + ExprResult buildAssignmentOperation(Scope *Sc,
> + SourceLocation opLoc,
> + BinaryOperatorKind opcode,
> + Expr *LHS, Expr *RHS);
> + Expr *rebuildAndCaptureObject(Expr *syntacticBase);
> +
> + bool findAtIndexGetter();
> + bool findAtIndexSetter();
> +
> + ExprResult buildGet();
> + ExprResult buildSet(Expr *op, SourceLocation, bool);
> + };
> +
> }
>
> /// Capture the given expression in an OpaqueValueExpr.
> @@ -718,6 +773,438 @@
> return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
> }
>
> +// ObjCSubscript build stuff.
> +//
> +
> +/// objective-c subscripting-specific behavior for doing lvalue-to-rvalue
> +/// conversion.
> +/// FIXME. Remove this routine if it is proven that no additional
> +/// specifity is needed.
> +ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) {
> + ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
> + if (result.isInvalid()) return ExprError();
> + return result;
> +}
> +
> +/// objective-c subscripting-specific behavior for doing assignments.
> +ExprResult
> +ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc,
> + SourceLocation opcLoc,
> + BinaryOperatorKind opcode,
> + Expr *LHS, Expr *RHS) {
> + assert(BinaryOperator::isAssignmentOp(opcode));
> + // There must be a method to do the Index'ed assignment.
> + if (!findAtIndexSetter())
> + return ExprError();
> +
> + // Verify that we can do a compound assignment.
> + if (opcode != BO_Assign && !findAtIndexGetter())
> + return ExprError();
> +
> + ExprResult result =
> + PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
> + if (result.isInvalid()) return ExprError();
> +
> + // Various warnings about objc Index'ed assignments in ARC.
> + if (S.getLangOptions().ObjCAutoRefCount && InstanceBase) {
> + S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS);
> + S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
> + }
> +
> + return result;
> +}
> +
> +/// Capture the base object of an Objective-C Index'ed expression.
> +Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
> + assert(InstanceBase == 0);
> +
> + // Capture base expression in an OVE and rebuild the syntactic
> + // form to use the OVE as its base expression.
> + InstanceBase = capture(RefExpr->getBaseExpr());
> + InstanceKey = capture(RefExpr->getKeyExpr());
> +
> + syntacticBase =
> + ObjCSubscriptRefRebuilder(S, InstanceBase,
> + InstanceKey).rebuild(syntacticBase);
> +
> + return syntacticBase;
> +}
> +
> +/// CheckSubscriptingKind - This routine decide what type
> +/// of indexing represented by "FromE" is being done.
> +Sema::ObjCSubscriptKind
> + Sema::CheckSubscriptingKind(Expr *FromE) {
> + // If the expression already has integral or enumeration type, we're golden.
> + QualType T = FromE->getType();
> + if (T->isIntegralOrEnumerationType())
> + return OS_Array;
> +
> + // If we don't have a class type in C++, there's no way we can get an
> + // expression of integral or enumeration type.
> + const RecordType *RecordTy = T->getAs<RecordType>();
> + if (!RecordTy)
> + // All other scalar cases are assumed to be dictionary indexing which
> + // caller handles, with diagnostics if needed.
> + return OS_Dictionary;
> + if (!getLangOptions().CPlusPlus || RecordTy->isIncompleteType()) {
> + // No indexing can be done. Issue diagnostics and quit.
> + Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
> + << FromE->getType();
> + return OS_Error;
> + }
> +
> + // We must have a complete class type.
> + if (RequireCompleteType(FromE->getExprLoc(), T,
> + PDiag(diag::err_objc_index_incomplete_class_type)
> + << FromE->getSourceRange()))
> + return OS_Error;
> +
> + // Look for a conversion to an integral, enumeration type, or
> + // objective-C pointer type.
> + UnresolvedSet<4> ViableConversions;
> + UnresolvedSet<4> ExplicitConversions;
> + const UnresolvedSetImpl *Conversions
> + = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
> +
> + int NoIntegrals=0, NoObjCIdPointers=0;
> + SmallVector<CXXConversionDecl *, 4> ConversionDecls;
> +
> + for (UnresolvedSetImpl::iterator I = Conversions->begin(),
> + E = Conversions->end();
> + I != E;
> + ++I) {
> + if (CXXConversionDecl *Conversion
> + = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) {
> + QualType CT = Conversion->getConversionType().getNonReferenceType();
> + if (CT->isIntegralOrEnumerationType()) {
> + ++NoIntegrals;
> + ConversionDecls.push_back(Conversion);
> + }
> + else if (CT->isObjCIdType() ||CT->isBlockPointerType()) {
> + ++NoObjCIdPointers;
> + ConversionDecls.push_back(Conversion);
> + }
> + }
> + }
> + if (NoIntegrals ==1 && NoObjCIdPointers == 0)
> + return OS_Array;
> + if (NoIntegrals == 0 && NoObjCIdPointers == 1)
> + return OS_Dictionary;
> + if (NoIntegrals == 0 && NoObjCIdPointers == 0) {
> + // No conversion function was found. Issue diagnostic and return.
> + Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
> + << FromE->getType();
> + return OS_Error;
> + }
> + Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion)
> + << FromE->getType();
> + for (unsigned int i = 0; i < ConversionDecls.size(); i++)
> + Diag(ConversionDecls[i]->getLocation(), diag::not_conv_function_declared_at);
> +
> + return OS_Error;
> +}
> +
> +bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
> + if (AtIndexGetter)
> + return true;
> +
> + Expr *BaseExpr = RefExpr->getBaseExpr();
> + QualType BaseT = BaseExpr->getType();
> +
> + QualType ResultType;
> + if (const ObjCObjectPointerType *PTy =
> + BaseT->getAs<ObjCObjectPointerType>()) {
> + ResultType = PTy->getPointeeType();
> + if (const ObjCObjectType *iQFaceTy =
> + ResultType->getAsObjCQualifiedInterfaceType())
> + ResultType = iQFaceTy->getBaseType();
> + }
> + Sema::ObjCSubscriptKind Res =
> + S.CheckSubscriptingKind(RefExpr->getKeyExpr());
> + if (Res == Sema::OS_Error)
> + return false;
> + bool arrayRef = (Res == Sema::OS_Array);
> +
> + if (ResultType.isNull()) {
> + S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
> + << BaseExpr->getType() << arrayRef;
> + return false;
> + }
> + if (!arrayRef) {
> + // dictionary subscripting.
> + // - (id)objectForKeyedSubscript:(id)key;
> + IdentifierInfo *KeyIdents[] = {
> + &S.Context.Idents.get("objectForKeyedSubscript")
> + };
> + AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
> + }
> + else {
> + // - (id)objectAtIndexedSubscript:(size_t)index;
> + IdentifierInfo *KeyIdents[] = {
> + &S.Context.Idents.get("objectAtIndexedSubscript")
> + };
> +
> + AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
> + }
> +
> + AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType,
> + true /*instance*/);
> + bool receiverIdType = (BaseT->isObjCIdType() ||
> + BaseT->isObjCQualifiedIdType());
> +
> + if (!AtIndexGetter && S.getLangOptions().DebuggerObjCLiteral) {
> + AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
> + SourceLocation(), AtIndexGetterSelector,
> + S.Context.getObjCIdType() /*ReturnType*/,
> + 0 /*TypeSourceInfo */,
> + S.Context.getTranslationUnitDecl(),
> + true /*Instance*/, false/*isVariadic*/,
> + /*isSynthesized=*/false,
> + /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
> + ObjCMethodDecl::Required,
> + false);
> + ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter,
> + SourceLocation(), SourceLocation(),
> + arrayRef ? &S.Context.Idents.get("index")
> + : &S.Context.Idents.get("key"),
> + arrayRef ? S.Context.UnsignedLongTy
> + : S.Context.getObjCIdType(),
> + /*TInfo=*/0,
> + SC_None,
> + SC_None,
> + 0);
> + AtIndexGetter->setMethodParams(S.Context, Argument,
> + ArrayRef<SourceLocation>());
> + }
> +
> + if (!AtIndexGetter) {
> + if (!receiverIdType) {
> + S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found)
> + << BaseExpr->getType() << 0 << arrayRef;
> + return false;
> + }
> + AtIndexGetter =
> + S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector,
> + RefExpr->getSourceRange(),
> + true, false);
> + }
> +
> + if (AtIndexGetter) {
> + QualType T = AtIndexGetter->param_begin()[0]->getType();
> + if ((arrayRef && !T->isIntegralOrEnumerationType()) ||
> + (!arrayRef && !T->isObjCObjectPointerType())) {
> + S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
> + arrayRef ? diag::err_objc_subscript_index_type
> + : diag::err_objc_subscript_key_type) << T;
> + S.Diag(AtIndexGetter->param_begin()[0]->getLocation(),
> + diag::note_parameter_type) << T;
> + return false;
> + }
> + QualType R = AtIndexGetter->getResultType();
> + if (!R->isObjCObjectPointerType()) {
> + S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
> + diag::err_objc_indexing_method_result_type) << R << arrayRef;
> + S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) <<
> + AtIndexGetter->getDeclName();
> + }
> + }
> + return true;
> +}
> +
> +bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
> + if (AtIndexSetter)
> + return true;
> +
> + Expr *BaseExpr = RefExpr->getBaseExpr();
> + QualType BaseT = BaseExpr->getType();
> +
> + QualType ResultType;
> + if (const ObjCObjectPointerType *PTy =
> + BaseT->getAs<ObjCObjectPointerType>()) {
> + ResultType = PTy->getPointeeType();
> + if (const ObjCObjectType *iQFaceTy =
> + ResultType->getAsObjCQualifiedInterfaceType())
> + ResultType = iQFaceTy->getBaseType();
> + }
> +
> + Sema::ObjCSubscriptKind Res =
> + S.CheckSubscriptingKind(RefExpr->getKeyExpr());
> + if (Res == Sema::OS_Error)
> + return false;
> + bool arrayRef = (Res == Sema::OS_Array);
> +
> + if (ResultType.isNull()) {
> + S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
> + << BaseExpr->getType() << arrayRef;
> + return false;
> + }
> +
> + if (!arrayRef) {
> + // dictionary subscripting.
> + // - (void)setObject:(id)object forKeyedSubscript:(id)key;
> + IdentifierInfo *KeyIdents[] = {
> + &S.Context.Idents.get("setObject"),
> + &S.Context.Idents.get("forKeyedSubscript")
> + };
> + AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
> + }
> + else {
> + // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
> + IdentifierInfo *KeyIdents[] = {
> + &S.Context.Idents.get("setObject"),
> + &S.Context.Idents.get("atIndexedSubscript")
> + };
> + AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
> + }
> + AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType,
> + true /*instance*/);
> +
> + bool receiverIdType = (BaseT->isObjCIdType() ||
> + BaseT->isObjCQualifiedIdType());
> +
> + if (!AtIndexSetter && S.getLangOptions().DebuggerObjCLiteral) {
> + TypeSourceInfo *ResultTInfo = 0;
> + QualType ReturnType = S.Context.VoidTy;
> + AtIndexSetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
> + SourceLocation(), AtIndexSetterSelector,
> + ReturnType,
> + ResultTInfo,
> + S.Context.getTranslationUnitDecl(),
> + true /*Instance*/, false/*isVariadic*/,
> + /*isSynthesized=*/false,
> + /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
> + ObjCMethodDecl::Required,
> + false);
> + SmallVector<ParmVarDecl *, 2> Params;
> + ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter,
> + SourceLocation(), SourceLocation(),
> + &S.Context.Idents.get("object"),
> + S.Context.getObjCIdType(),
> + /*TInfo=*/0,
> + SC_None,
> + SC_None,
> + 0);
> + Params.push_back(object);
> + ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,
> + SourceLocation(), SourceLocation(),
> + arrayRef ? &S.Context.Idents.get("index")
> + : &S.Context.Idents.get("key"),
> + arrayRef ? S.Context.UnsignedLongTy
> + : S.Context.getObjCIdType(),
> + /*TInfo=*/0,
> + SC_None,
> + SC_None,
> + 0);
> + Params.push_back(key);
> + AtIndexSetter->setMethodParams(S.Context, Params, ArrayRef<SourceLocation>());
> + }
> +
> + if (!AtIndexSetter) {
> + if (!receiverIdType) {
> + S.Diag(BaseExpr->getExprLoc(),
> + diag::err_objc_subscript_method_not_found)
> + << BaseExpr->getType() << 1 << arrayRef;
> + return false;
> + }
> + AtIndexSetter =
> + S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector,
> + RefExpr->getSourceRange(),
> + true, false);
> + }
> +
> + bool err = false;
> + if (AtIndexSetter && arrayRef) {
> + QualType T = AtIndexSetter->param_begin()[1]->getType();
> + if (!T->isIntegralOrEnumerationType()) {
> + S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
> + diag::err_objc_subscript_index_type) << T;
> + S.Diag(AtIndexSetter->param_begin()[1]->getLocation(),
> + diag::note_parameter_type) << T;
> + err = true;
> + }
> + T = AtIndexSetter->param_begin()[0]->getType();
> + if (!T->isObjCObjectPointerType()) {
> + S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
> + diag::err_objc_subscript_object_type) << T << arrayRef;
> + S.Diag(AtIndexSetter->param_begin()[0]->getLocation(),
> + diag::note_parameter_type) << T;
> + err = true;
> + }
> + }
> + else if (AtIndexSetter && !arrayRef)
> + for (unsigned i=0; i <2; i++) {
> + QualType T = AtIndexSetter->param_begin()[i]->getType();
> + if (!T->isObjCObjectPointerType()) {
> + if (i == 1)
> + S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
> + diag::err_objc_subscript_key_type) << T;
> + else
> + S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
> + diag::err_objc_subscript_dic_object_type) << T;
> + S.Diag(AtIndexSetter->param_begin()[i]->getLocation(),
> + diag::note_parameter_type) << T;
> + err = true;
> + }
> + }
> +
> + return !err;
> +}
> +
> +// Get the object at "Index" position in the container.
> +// [BaseExpr objectAtIndexedSubscript : IndexExpr];
> +ExprResult ObjCSubscriptOpBuilder::buildGet() {
> + if (!findAtIndexGetter())
> + return ExprError();
> +
> + QualType receiverType = InstanceBase->getType();
> +
> + // Build a message-send.
> + ExprResult msg;
> + Expr *Index = InstanceKey;
> +
> + // Arguments.
> + Expr *args[] = { Index };
> + assert(InstanceBase);
> + msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
> + GenericLoc,
> + AtIndexGetterSelector, AtIndexGetter,
> + MultiExprArg(args, 1));
> + return msg;
> +}
> +
> +/// Store into the container the "op" object at "Index"'ed location
> +/// by building this messaging expression:
> +/// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
> +/// \param bindSetValueAsResult - If true, capture the actual
> +/// value being set as the value of the property operation.
> +ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
> + bool captureSetValueAsResult) {
> + if (!findAtIndexSetter())
> + return ExprError();
> +
> + QualType receiverType = InstanceBase->getType();
> + Expr *Index = InstanceKey;
> +
> + // Arguments.
> + Expr *args[] = { op, Index };
> +
> + // Build a message-send.
> + ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
> + GenericLoc,
> + AtIndexSetterSelector,
> + AtIndexSetter,
> + MultiExprArg(args, 2));
> +
> + if (!msg.isInvalid() && captureSetValueAsResult) {
> + ObjCMessageExpr *msgExpr =
> + cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
> + Expr *arg = msgExpr->getArg(0);
> + msgExpr->setArg(0, captureValueAsResult(arg));
> + }
> +
> + return msg;
> +}
> +
> //===----------------------------------------------------------------------===//
> // General Sema routines.
> //===----------------------------------------------------------------------===//
> @@ -728,6 +1215,11 @@
> = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
> ObjCPropertyOpBuilder builder(*this, refExpr);
> return builder.buildRValueOperation(E);
> + }
> + else if (ObjCSubscriptRefExpr *refExpr
> + = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
> + ObjCSubscriptOpBuilder builder(*this, refExpr);
> + return builder.buildRValueOperation(E);
> } else {
> llvm_unreachable("unknown pseudo-object kind!");
> }
> @@ -747,6 +1239,9 @@
> = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
> ObjCPropertyOpBuilder builder(*this, refExpr);
> return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
> + } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
> + Diag(opcLoc, diag::err_illegal_container_subscripting_op);
> + return ExprError();
> } else {
> llvm_unreachable("unknown pseudo-object kind!");
> }
> @@ -772,6 +1267,10 @@
> = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
> ObjCPropertyOpBuilder builder(*this, refExpr);
> return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
> + } else if (ObjCSubscriptRefExpr *refExpr
> + = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
> + ObjCSubscriptOpBuilder builder(*this, refExpr);
> + return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
> } else {
> llvm_unreachable("unknown pseudo-object kind!");
> }
> @@ -786,6 +1285,12 @@
> = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
> OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase());
> return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
> + } else if (ObjCSubscriptRefExpr *refExpr
> + = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
> + OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr());
> + OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr());
> + return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(),
> + keyOVE->getSourceExpr()).rebuild(E);
> } else {
> llvm_unreachable("unknown pseudo-object kind!");
> }
>
> Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaStmt.cpp Tue Mar 6 14:05:56 2012
> @@ -199,8 +199,12 @@
> Diag(Loc, diag::warn_unused_result) << R1 << R2;
> return;
> }
> - } else if (isa<PseudoObjectExpr>(E)) {
> - DiagID = diag::warn_unused_property_expr;
> + } else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
> + const Expr *Source = POE->getSyntacticForm();
> + if (isa<ObjCSubscriptRefExpr>(Source))
> + DiagID = diag::warn_unused_container_subscript_expr;
> + else
> + DiagID = diag::warn_unused_property_expr;
> } else if (const CXXFunctionalCastExpr *FC
> = dyn_cast<CXXFunctionalCastExpr>(E)) {
> if (isa<CXXConstructExpr>(FC->getSubExpr()) ||
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Tue Mar 6 14:05:56 2012
> @@ -93,6 +93,22 @@
> return inherited::TraverseTemplateName(Template);
> }
>
> + /// \brief Suppress traversal into Objective-C container literal
> + /// elements that are pack expansions.
> + bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
> + if (!E->containsUnexpandedParameterPack())
> + return true;
> +
> + for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) {
> + ObjCDictionaryElement Element = E->getKeyValueElement(I);
> + if (Element.isPackExpansion())
> + continue;
> +
> + TraverseStmt(Element.Key);
> + TraverseStmt(Element.Value);
> + }
> + return true;
> + }
> //------------------------------------------------------------------------
> // Pruning the search for unexpanded parameter packs.
> //------------------------------------------------------------------------
>
> Modified: cfe/trunk/lib/Sema/TreeTransform.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
> +++ cfe/trunk/lib/Sema/TreeTransform.h Tue Mar 6 14:05:56 2012
> @@ -2210,7 +2210,35 @@
> OperatorLoc, Pack, PackLoc,
> RParenLoc);
> }
> -
> +
> + /// \brief Build a new Objective-C array literal.
> + ///
> + /// By default, performs semantic analysis to build the new expression.
> + /// Subclasses may override this routine to provide different behavior.
> + ExprResult RebuildObjCArrayLiteral(SourceRange Range,
> + Expr **Elements, unsigned NumElements) {
> + return getSema().BuildObjCArrayLiteral(Range,
> + MultiExprArg(Elements, NumElements));
> + }
> +
> + ExprResult RebuildObjCSubscriptRefExpr(SourceLocation RB,
> + Expr *Base, Expr *Key,
> + ObjCMethodDecl *getterMethod,
> + ObjCMethodDecl *setterMethod) {
> + return getSema().BuildObjCSubscriptExpression(RB, Base, Key,
> + getterMethod, setterMethod);
> + }
> +
> + /// \brief Build a new Objective-C dictionary literal.
> + ///
> + /// By default, performs semantic analysis to build the new expression.
> + /// Subclasses may override this routine to provide different behavior.
> + ExprResult RebuildObjCDictionaryLiteral(SourceRange Range,
> + ObjCDictionaryElement *Elements,
> + unsigned NumElements) {
> + return getSema().BuildObjCDictionaryLiteral(Range, Elements, NumElements);
> + }
> +
> /// \brief Build a new Objective-C @encode expression.
> ///
> /// By default, performs semantic analysis to build the new expression.
> @@ -8253,7 +8281,159 @@
> template<typename Derived>
> ExprResult
> TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) {
> - return SemaRef.Owned(E);
> + return SemaRef.MaybeBindToTemporary(E);
> +}
> +
> +template<typename Derived>
> +ExprResult
> +TreeTransform<Derived>::TransformObjCBoolLiteralExpr(ObjCBoolLiteralExpr *E) {
> + return SemaRef.MaybeBindToTemporary(E);
> +}
> +
> +template<typename Derived>
> +ExprResult
> +TreeTransform<Derived>::TransformObjCNumericLiteral(ObjCNumericLiteral *E) {
> + return SemaRef.MaybeBindToTemporary(E);
> +}
> +
> +template<typename Derived>
> +ExprResult
> +TreeTransform<Derived>::TransformObjCArrayLiteral(ObjCArrayLiteral *E) {
> + // Transform each of the elements.
> + llvm::SmallVector<Expr *, 8> Elements;
> + bool ArgChanged = false;
> + if (getDerived().TransformExprs(E->getElements(), E->getNumElements(),
> + /*IsCall=*/false, Elements, &ArgChanged))
> + return ExprError();
> +
> + if (!getDerived().AlwaysRebuild() && !ArgChanged)
> + return SemaRef.MaybeBindToTemporary(E);
> +
> + return getDerived().RebuildObjCArrayLiteral(E->getSourceRange(),
> + Elements.data(),
> + Elements.size());
> +}
> +
> +template<typename Derived>
> +ExprResult
> +TreeTransform<Derived>::TransformObjCDictionaryLiteral(
> + ObjCDictionaryLiteral *E) {
> + // Transform each of the elements.
> + llvm::SmallVector<ObjCDictionaryElement, 8> Elements;
> + bool ArgChanged = false;
> + for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) {
> + ObjCDictionaryElement OrigElement = E->getKeyValueElement(I);
> +
> + if (OrigElement.isPackExpansion()) {
> + // This key/value element is a pack expansion.
> + SmallVector<UnexpandedParameterPack, 2> Unexpanded;
> + getSema().collectUnexpandedParameterPacks(OrigElement.Key, Unexpanded);
> + getSema().collectUnexpandedParameterPacks(OrigElement.Value, Unexpanded);
> + assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
> +
> + // Determine whether the set of unexpanded parameter packs can
> + // and should be expanded.
> + bool Expand = true;
> + bool RetainExpansion = false;
> + llvm::Optional<unsigned> OrigNumExpansions = OrigElement.NumExpansions;
> + llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
> + SourceRange PatternRange(OrigElement.Key->getLocStart(),
> + OrigElement.Value->getLocEnd());
> + if (getDerived().TryExpandParameterPacks(OrigElement.EllipsisLoc,
> + PatternRange,
> + Unexpanded,
> + Expand, RetainExpansion,
> + NumExpansions))
> + return ExprError();
> +
> + if (!Expand) {
> + // The transform has determined that we should perform a simple
> + // transformation on the pack expansion, producing another pack
> + // expansion.
> + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
> + ExprResult Key = getDerived().TransformExpr(OrigElement.Key);
> + if (Key.isInvalid())
> + return ExprError();
> +
> + if (Key.get() != OrigElement.Key)
> + ArgChanged = true;
> +
> + ExprResult Value = getDerived().TransformExpr(OrigElement.Value);
> + if (Value.isInvalid())
> + return ExprError();
> +
> + if (Value.get() != OrigElement.Value)
> + ArgChanged = true;
> +
> + ObjCDictionaryElement Expansion = {
> + Key.get(), Value.get(), OrigElement.EllipsisLoc, NumExpansions
> + };
> + Elements.push_back(Expansion);
> + continue;
> + }
> +
> + // Record right away that the argument was changed. This needs
> + // to happen even if the array expands to nothing.
> + ArgChanged = true;
> +
> + // The transform has determined that we should perform an elementwise
> + // expansion of the pattern. Do so.
> + for (unsigned I = 0; I != *NumExpansions; ++I) {
> + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
> + ExprResult Key = getDerived().TransformExpr(OrigElement.Key);
> + if (Key.isInvalid())
> + return ExprError();
> +
> + ExprResult Value = getDerived().TransformExpr(OrigElement.Value);
> + if (Value.isInvalid())
> + return ExprError();
> +
> + ObjCDictionaryElement Element = {
> + Key.get(), Value.get(), SourceLocation(), NumExpansions
> + };
> +
> + // If any unexpanded parameter packs remain, we still have a
> + // pack expansion.
> + if (Key.get()->containsUnexpandedParameterPack() ||
> + Value.get()->containsUnexpandedParameterPack())
> + Element.EllipsisLoc = OrigElement.EllipsisLoc;
> +
> + Elements.push_back(Element);
> + }
> +
> + // We've finished with this pack expansion.
> + continue;
> + }
> +
> + // Transform and check key.
> + ExprResult Key = getDerived().TransformExpr(OrigElement.Key);
> + if (Key.isInvalid())
> + return ExprError();
> +
> + if (Key.get() != OrigElement.Key)
> + ArgChanged = true;
> +
> + // Transform and check value.
> + ExprResult Value
> + = getDerived().TransformExpr(OrigElement.Value);
> + if (Value.isInvalid())
> + return ExprError();
> +
> + if (Value.get() != OrigElement.Value)
> + ArgChanged = true;
> +
> + ObjCDictionaryElement Element = {
> + Key.get(), Value.get(), SourceLocation(), llvm::Optional<unsigned>()
> + };
> + Elements.push_back(Element);
> + }
> +
> + if (!getDerived().AlwaysRebuild() && !ArgChanged)
> + return SemaRef.MaybeBindToTemporary(E);
> +
> + return getDerived().RebuildObjCDictionaryLiteral(E->getSourceRange(),
> + Elements.data(),
> + Elements.size());
> }
>
> template<typename Derived>
> @@ -8436,6 +8616,30 @@
>
> template<typename Derived>
> ExprResult
> +TreeTransform<Derived>::TransformObjCSubscriptRefExpr(ObjCSubscriptRefExpr *E) {
> + // Transform the base expression.
> + ExprResult Base = getDerived().TransformExpr(E->getBaseExpr());
> + if (Base.isInvalid())
> + return ExprError();
> +
> + // Transform the key expression.
> + ExprResult Key = getDerived().TransformExpr(E->getKeyExpr());
> + if (Key.isInvalid())
> + return ExprError();
> +
> + // If nothing changed, just retain the existing expression.
> + if (!getDerived().AlwaysRebuild() &&
> + Key.get() == E->getKeyExpr() && Base.get() == E->getBaseExpr())
> + return SemaRef.Owned(E);
> +
> + return getDerived().RebuildObjCSubscriptRefExpr(E->getRBracket(),
> + Base.get(), Key.get(),
> + E->getAtIndexMethodDecl(),
> + E->setAtIndexMethodDecl());
> +}
> +
> +template<typename Derived>
> +ExprResult
> TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) {
> // Transform the base expression.
> ExprResult Base = getDerived().TransformExpr(E->getBase());
>
> Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Tue Mar 6 14:05:56 2012
> @@ -823,6 +823,45 @@
> E->setAtLoc(ReadSourceLocation(Record, Idx));
> }
>
> +void ASTStmtReader::VisitObjCNumericLiteral(ObjCNumericLiteral *E) {
> + VisitExpr(E);
> + // could be one of several IntegerLiteral, FloatLiteral, etc.
> + E->Number = Reader.ReadSubStmt();
> + E->ObjCNumericLiteralMethod = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
> + E->AtLoc = ReadSourceLocation(Record, Idx);
> +}
> +
> +void ASTStmtReader::VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
> + VisitExpr(E);
> + unsigned NumElements = Record[Idx++];
> + assert(NumElements == E->getNumElements() && "Wrong number of elements");
> + Expr **Elements = E->getElements();
> + for (unsigned I = 0, N = NumElements; I != N; ++I)
> + Elements[I] = Reader.ReadSubExpr();
> + E->ArrayWithObjectsMethod = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
> + E->Range = ReadSourceRange(Record, Idx);
> +}
> +
> +void ASTStmtReader::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
> + VisitExpr(E);
> + unsigned NumElements = Record[Idx++];
> + assert(NumElements == E->getNumElements() && "Wrong number of elements");
> + bool HasPackExpansions = Record[Idx++];
> + assert(HasPackExpansions == E->HasPackExpansions &&"Pack expansion mismatch");
> + ObjCDictionaryLiteral::KeyValuePair *KeyValues = E->getKeyValues();
> + ObjCDictionaryLiteral::ExpansionData *Expansions = E->getExpansionData();
> + for (unsigned I = 0; I != NumElements; ++I) {
> + KeyValues[I].Key = Reader.ReadSubExpr();
> + KeyValues[I].Value = Reader.ReadSubExpr();
> + if (HasPackExpansions) {
> + Expansions[I].EllipsisLoc = ReadSourceLocation(Record, Idx);
> + Expansions[I].NumExpansionsPlusOne = Record[Idx++];
> + }
> + }
> + E->DictWithObjectsMethod = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
> + E->Range = ReadSourceRange(Record, Idx);
> +}
> +
> void ASTStmtReader::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
> VisitExpr(E);
> E->setEncodedTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
> @@ -878,6 +917,15 @@
> }
> }
>
> +void ASTStmtReader::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *E) {
> + VisitExpr(E);
> + E->setRBracket(ReadSourceLocation(Record, Idx));
> + E->setBaseExpr(Reader.ReadSubExpr());
> + E->setKeyExpr(Reader.ReadSubExpr());
> + E->GetAtIndexMethodDecl = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
> + E->SetAtIndexMethodDecl = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
> +}
> +
> void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) {
> VisitExpr(E);
> assert(Record[Idx] == E->getNumArgs());
> @@ -980,6 +1028,12 @@
> S->setThrowLoc(ReadSourceLocation(Record, Idx));
> }
>
> +void ASTStmtReader::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *E) {
> + VisitExpr(E);
> + E->setValue(Record[Idx++]);
> + E->setLocation(ReadSourceLocation(Record, Idx));
> +}
> +
> //===----------------------------------------------------------------------===//
> // C++ Expressions and Statements
> //===----------------------------------------------------------------------===//
> @@ -1834,6 +1888,18 @@
> case EXPR_OBJC_STRING_LITERAL:
> S = new (Context) ObjCStringLiteral(Empty);
> break;
> + case EXPR_OBJC_NUMERIC_LITERAL:
> + S = new (Context) ObjCNumericLiteral(Empty);
> + break;
> + case EXPR_OBJC_ARRAY_LITERAL:
> + S = ObjCArrayLiteral::CreateEmpty(Context,
> + Record[ASTStmtReader::NumExprFields]);
> + break;
> + case EXPR_OBJC_DICTIONARY_LITERAL:
> + S = ObjCDictionaryLiteral::CreateEmpty(Context,
> + Record[ASTStmtReader::NumExprFields],
> + Record[ASTStmtReader::NumExprFields + 1]);
> + break;
> case EXPR_OBJC_ENCODE:
> S = new (Context) ObjCEncodeExpr(Empty);
> break;
> @@ -1849,6 +1915,9 @@
> case EXPR_OBJC_PROPERTY_REF_EXPR:
> S = new (Context) ObjCPropertyRefExpr(Empty);
> break;
> + case EXPR_OBJC_SUBSCRIPT_REF_EXPR:
> + S = new (Context) ObjCSubscriptRefExpr(Empty);
> + break;
> case EXPR_OBJC_KVC_REF_EXPR:
> llvm_unreachable("mismatching AST file");
> case EXPR_OBJC_MESSAGE_EXPR:
> @@ -1888,6 +1957,9 @@
> case STMT_OBJC_AUTORELEASE_POOL:
> S = new (Context) ObjCAutoreleasePoolStmt(Empty);
> break;
> + case EXPR_OBJC_BOOL_LITERAL:
> + S = new (Context) ObjCBoolLiteralExpr(Empty);
> + break;
> case STMT_SEH_EXCEPT:
> S = new (Context) SEHExceptStmt(Empty);
> break;
>
> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Mar 6 14:05:56 2012
> @@ -696,6 +696,9 @@
> RECORD(EXPR_BLOCK_DECL_REF);
> RECORD(EXPR_GENERIC_SELECTION);
> RECORD(EXPR_OBJC_STRING_LITERAL);
> + RECORD(EXPR_OBJC_NUMERIC_LITERAL);
> + RECORD(EXPR_OBJC_ARRAY_LITERAL);
> + RECORD(EXPR_OBJC_DICTIONARY_LITERAL);
> RECORD(EXPR_OBJC_ENCODE);
> RECORD(EXPR_OBJC_SELECTOR_EXPR);
> RECORD(EXPR_OBJC_PROTOCOL_EXPR);
> @@ -709,6 +712,7 @@
> RECORD(STMT_OBJC_AT_TRY);
> RECORD(STMT_OBJC_AT_SYNCHRONIZED);
> RECORD(STMT_OBJC_AT_THROW);
> + RECORD(EXPR_OBJC_BOOL_LITERAL);
> RECORD(EXPR_CXX_OPERATOR_CALL);
> RECORD(EXPR_CXX_CONSTRUCT);
> RECORD(EXPR_CXX_STATIC_CAST);
>
> Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Tue Mar 6 14:05:56 2012
> @@ -753,7 +753,6 @@
> i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) {
> Writer.AddStmt(*i);
> }
> -
> Code = serialization::EXPR_PSEUDO_OBJECT;
> }
>
> @@ -770,7 +769,6 @@
> }
> Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
> Writer.AddSourceLocation(E->getRParenLoc(), Record);
> -
> Code = serialization::EXPR_ATOMIC;
> }
>
> @@ -785,6 +783,46 @@
> Code = serialization::EXPR_OBJC_STRING_LITERAL;
> }
>
> +void ASTStmtWriter::VisitObjCNumericLiteral(ObjCNumericLiteral *E) {
> + VisitExpr(E);
> + Writer.AddStmt(E->getNumber());
> + Writer.AddDeclRef(E->getObjCNumericLiteralMethod(), Record);
> + Writer.AddSourceLocation(E->getAtLoc(), Record);
> + Code = serialization::EXPR_OBJC_NUMERIC_LITERAL;
> +}
> +
> +void ASTStmtWriter::VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
> + VisitExpr(E);
> + Record.push_back(E->getNumElements());
> + for (unsigned i = 0; i < E->getNumElements(); i++)
> + Writer.AddStmt(E->getElement(i));
> + Writer.AddDeclRef(E->getArrayWithObjectsMethod(), Record);
> + Writer.AddSourceRange(E->getSourceRange(), Record);
> + Code = serialization::EXPR_OBJC_ARRAY_LITERAL;
> +}
> +
> +void ASTStmtWriter::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
> + VisitExpr(E);
> + Record.push_back(E->getNumElements());
> + Record.push_back(E->HasPackExpansions);
> + for (unsigned i = 0; i < E->getNumElements(); i++) {
> + ObjCDictionaryElement Element = E->getKeyValueElement(i);
> + Writer.AddStmt(Element.Key);
> + Writer.AddStmt(Element.Value);
> + if (E->HasPackExpansions) {
> + Writer.AddSourceLocation(Element.EllipsisLoc, Record);
> + unsigned NumExpansions = 0;
> + if (Element.NumExpansions)
> + NumExpansions = *Element.NumExpansions + 1;
> + Record.push_back(NumExpansions);
> + }
> + }
> +
> + Writer.AddDeclRef(E->getDictWithObjectsMethod(), Record);
> + Writer.AddSourceRange(E->getSourceRange(), Record);
> + Code = serialization::EXPR_OBJC_DICTIONARY_LITERAL;
> +}
> +
> void ASTStmtWriter::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
> VisitExpr(E);
> Writer.AddTypeSourceInfo(E->getEncodedTypeSourceInfo(), Record);
> @@ -844,6 +882,17 @@
> Code = serialization::EXPR_OBJC_PROPERTY_REF_EXPR;
> }
>
> +void ASTStmtWriter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *E) {
> + VisitExpr(E);
> + Writer.AddSourceLocation(E->getRBracket(), Record);
> + Writer.AddStmt(E->getBaseExpr());
> + Writer.AddStmt(E->getKeyExpr());
> + Writer.AddDeclRef(E->getAtIndexMethodDecl(), Record);
> + Writer.AddDeclRef(E->setAtIndexMethodDecl(), Record);
> +
> + Code = serialization::EXPR_OBJC_SUBSCRIPT_REF_EXPR;
> +}
> +
> void ASTStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
> VisitExpr(E);
> Record.push_back(E->getNumArgs());
> @@ -945,6 +994,13 @@
> Code = serialization::STMT_OBJC_AT_THROW;
> }
>
> +void ASTStmtWriter::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *E) {
> + VisitExpr(E);
> + Record.push_back(E->getValue());
> + Writer.AddSourceLocation(E->getLocation(), Record);
> + Code = serialization::EXPR_OBJC_BOOL_LITERAL;
> +}
> +
> //===----------------------------------------------------------------------===//
> // C++ Expressions and Statements.
> //===----------------------------------------------------------------------===//
>
> Added: cfe/trunk/test/CodeGenObjC/Inputs/literal-support.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/Inputs/literal-support.h?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/Inputs/literal-support.h (added)
> +++ cfe/trunk/test/CodeGenObjC/Inputs/literal-support.h Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,35 @@
> +#ifndef OBJC_LITERAL_SUPPORT_H
> +#define OBJC_LITERAL_SUPPORT_H
> +
> +typedef unsigned char BOOL;
> +
> + at interface NSNumber @end
> +
> + at interface NSNumber (NSNumberCreation)
> ++ (NSNumber *)numberWithChar:(char)value;
> ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
> ++ (NSNumber *)numberWithShort:(short)value;
> ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
> ++ (NSNumber *)numberWithInt:(int)value;
> ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
> ++ (NSNumber *)numberWithLong:(long)value;
> ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
> ++ (NSNumber *)numberWithLongLong:(long long)value;
> ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
> ++ (NSNumber *)numberWithFloat:(float)value;
> ++ (NSNumber *)numberWithDouble:(double)value;
> ++ (NSNumber *)numberWithBool:(BOOL)value;
> + at end
> +
> + at interface NSArray
> + at end
> +
> + at interface NSArray (NSArrayCreation)
> ++ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt;
> + at end
> +
> + at interface NSDictionary
> ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
> + at end
> +
> +#endif // OBJC_LITERAL_SUPPORT_H
>
> Added: cfe/trunk/test/CodeGenObjC/arc-literals.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-literals.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/arc-literals.m (added)
> +++ cfe/trunk/test/CodeGenObjC/arc-literals.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,121 @@
> +// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s
> +
> +#include "literal-support.h"
> +
> +// Check the various selector names we'll be using, in order.
> +
> +// CHECK: c"numberWithInt:\00"
> +// CHECK: c"numberWithUnsignedInt:\00"
> +// CHECK: c"numberWithUnsignedLongLong:\00"
> +// CHECK: c"numberWithChar:\00"
> +// CHECK: c"arrayWithObjects:count:\00"
> +// CHECK: c"dictionaryWithObjects:forKeys:count:\00"
> +// CHECK: c"prop\00"
> +
> +// CHECK: define void @test_numeric()
> +void test_numeric() {
> + // CHECK: {{call.*objc_msgSend.*i32 17}}
> + // CHECK: call i8* @objc_retainAutoreleasedReturnValue
> + id ilit = @17;
> + // CHECK: {{call.*objc_msgSend.*i32 25}}
> + // CHECK: call i8* @objc_retainAutoreleasedReturnValue
> + id ulit = @25u;
> + // CHECK: {{call.*objc_msgSend.*i64 42}}
> + // CHECK: call i8* @objc_retainAutoreleasedReturnValue
> + id ulllit = @42ull;
> + // CHECK: {{call.*objc_msgSend.*i8 signext 97}}
> + // CHECK: call i8* @objc_retainAutoreleasedReturnValue
> + id charlit = @'a';
> + // CHECK: call void @objc_release
> + // CHECK: call void @objc_release
> + // CHECK: call void @objc_release
> + // CHECK: call void @objc_release
> + // CHECK-NEXT: ret void
> +}
> +
> +// CHECK: define void @test_array
> +void test_array(id a, id b) {
> + // Retaining parameters
> + // CHECK: call i8* @objc_retain(i8*
> + // CHECK: call i8* @objc_retain(i8*
> +
> + // Constructing the array
> + // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS:%[A-Za-z0-9]+]], i32 0, i32 0
> + // CHECK: store i8*
> + // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1
> + // CHECK: store i8*
> +
> + // CHECK: {{call i8*.*objc_msgSend.*i64 2}}
> + // CHECK: call i8* @objc_retainAutoreleasedReturnValue
> + id arr = @[a, b];
> +
> + // CHECK: call void @objc_release
> + // CHECK: call void @objc_release
> + // CHECK: call void @objc_release
> + // CHECK-NEXT: ret void
> +}
> +
> +// CHECK: define void @test_dictionary
> +void test_dictionary(id k1, id o1, id k2, id o2) {
> + // Retaining parameters
> + // CHECK: call i8* @objc_retain(i8*
> + // CHECK: call i8* @objc_retain(i8*
> + // CHECK: call i8* @objc_retain(i8*
> + // CHECK: call i8* @objc_retain(i8*
> +
> + // Constructing the arrays
> + // CHECK: getelementptr inbounds [2 x i8*]* [[KEYS:%[A-Za-z0-9]+]], i32 0, i32 0
> + // CHECK: store i8*
> + // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS:%[A-Za-z0-9]+]], i32 0, i32 0
> + // CHECK: store i8*
> + // CHECK: getelementptr inbounds [2 x i8*]* [[KEYS]], i32 0, i32 1
> + // CHECK: store i8*
> + // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1
> + // CHECK: store i8*
> +
> + // Constructing the dictionary
> + // CHECK: {{call i8.*@objc_msgSend}}
> + // CHECK: call i8* @objc_retainAutoreleasedReturnValue
> + id dict = @{ k1 : o1, k2 : o2 };
> +
> + // CHECK: call void @objc_release
> + // CHECK: call void @objc_release
> + // CHECK: call void @objc_release
> + // CHECK: call void @objc_release
> + // CHECK: call void @objc_release
> + // CHECK-NEXT: ret void
> +}
> +
> + at interface A
> + at end
> +
> + at interface B
> + at property (retain) A* prop;
> + at end
> +
> +// CHECK: define void @test_property
> +void test_property(B *b) {
> + // Retain parameter
> + // CHECK: call i8* @objc_retain
> +
> + // Invoke 'prop'
> + // CHECK: load i8** @"\01L_OBJC_SELECTOR_REFERENCES
> + // CHECK: {{call.*@objc_msgSend}}
> + // CHECK: call i8* @objc_retainAutoreleasedReturnValue
> +
> + // Invoke arrayWithObjects:count:
> + // CHECK: load i8** @"\01L_OBJC_SELECTOR_REFERENCES
> + // CHECK: {{call.*objc_msgSend}}
> + // CHECK: call i8* @objc_retainAutoreleasedReturnValue
> + id arr = @[ b.prop ];
> +
> + // Release b.prop
> + // CHECK: call void @objc_release
> +
> + // Destroy arr
> + // CHECK: call void @objc_release
> +
> + // Destroy b
> + // CHECK: call void @objc_release
> + // CHECK-NEXT: ret void
> +}
>
> Added: cfe/trunk/test/CodeGenObjC/objc-arc-container-subscripting.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/objc-arc-container-subscripting.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/objc-arc-container-subscripting.m (added)
> +++ cfe/trunk/test/CodeGenObjC/objc-arc-container-subscripting.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,21 @@
> +// RUN: %clang_cc1 -fobjc-arc -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s
> +
> + at interface NSMutableArray
> +- (id)objectAtIndexedSubscript:(int)index;
> +- (void)setObject:(id)object atIndexedSubscript:(int)index;
> + at end
> +
> +id func() {
> + NSMutableArray *array;
> + array[3] = 0;
> + return array[3];
> +}
> +
> +// CHECK: [[call:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
> +// CHECK: [[SIX:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[call]]) nounwind
> +// CHECK: [[ARRAY:%.*]] = load %0**
> +// CHECK: [[ARRAY_CASTED:%.*]] = bitcast{{.*}}[[ARRAY]] to i8*
> +// CHECK: call void @objc_release(i8* [[ARRAY_CASTED]])
> +// CHECK: [[EIGHT:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[SIX]]) nounwind
> +// CHECK: ret i8* [[EIGHT]]
> +
>
> Added: cfe/trunk/test/CodeGenObjC/objc-container-subscripting-1.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/objc-container-subscripting-1.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/objc-container-subscripting-1.m (added)
> +++ cfe/trunk/test/CodeGenObjC/objc-container-subscripting-1.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,56 @@
> +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s
> +
> +typedef unsigned int size_t;
> + at protocol P @end
> +
> + at interface NSMutableArray
> +- (id)objectAtIndexedSubscript:(size_t)index;
> +- (void)setObject:(id)object atIndexedSubscript:(size_t)index;
> + at end
> +
> + at interface NSMutableDictionary
> +- (id)objectForKeyedSubscript:(id)key;
> +- (void)setObject:(id)object forKeyedSubscript:(id)key;
> + at end
> +
> +int main() {
> + NSMutableArray *array;
> + id val;
> +
> + id oldObject = array[10];
> +// CHECK: [[ARR:%.*]] = load {{%.*}} [[array:%.*]], align 8
> +// CHECK-NEXT: [[SEL:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_"
> +// CHECK-NEXT: [[ARRC:%.*]] = bitcast {{%.*}} [[ARR]] to i8*
> +// CHECK-NEXT: [[CALL:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i32)*)(i8* [[ARRC]], i8* [[SEL]], i32 10)
> +// CHECK-NEXT: store i8* [[CALL]], i8** [[OLDOBJ:%.*]], align 8
> +
> + val = (array[10] = oldObject);
> +// CHECK: [[THREE:%.*]] = load {{%.*}} [[array:%.*]], align 8
> +// CHECK-NEXT: [[FOUR:%.*]] = load i8** [[oldObject:%.*]], align 8
> +// CHECK-NEXT: [[FIVE:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_2"
> +// CHECK-NEXT: [[SIX:%.*]] = bitcast {{%.*}} [[THREE]] to i8*
> +// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i32)*)(i8* [[SIX]], i8* [[FIVE]], i8* [[FOUR]], i32 10)
> +// CHECK-NEXT: store i8* [[FOUR]], i8** [[val:%.*]]
> +
> + NSMutableDictionary *dictionary;
> + id key;
> + id newObject;
> + oldObject = dictionary[key];
> +// CHECK: [[SEVEN:%.*]] = load {{%.*}} [[DICTIONARY:%.*]], align 8
> +// CHECK-NEXT: [[EIGHT:%.*]] = load i8** [[KEY:%.*]], align 8
> +// CHECK-NEXT: [[TEN:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_4"
> +// CHECK-NEXT: [[ELEVEN:%.*]] = bitcast {{%.*}} [[SEVEN]] to i8*
> +// CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i8*)*)(i8* [[ELEVEN]], i8* [[TEN]], i8* [[EIGHT]])
> +// CHECK-NEXT: store i8* [[CALL1]], i8** [[oldObject:%.*]], align 8
> +
> +
> + val = (dictionary[key] = newObject);
> +// CHECK: [[TWELVE:%.*]] = load {{%.*}} [[DICTIONARY]], align 8
> +// CHECK-NEXT: [[THIRTEEN:%.*]] = load i8** [[KEY]], align 8
> +// CHECK-NEXT: [[FOURTEEN:%.*]] = load i8** [[NEWOBJECT:%.*]], align 8
> +// CHECK-NEXT: [[SIXTEEN:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_6"
> +// CHECK-NEXT: [[SEVENTEEN:%.*]] = bitcast {{%.*}} [[TWELVE]] to i8*
> +// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i8*)*)(i8* [[SEVENTEEN]], i8* [[SIXTEEN]], i8* [[FOURTEEN]], i8* [[THIRTEEN]])
> +// CHECK-NEXT: store i8* [[FOURTEEN]], i8** [[val:%.*]]
> +}
> +
>
> Added: cfe/trunk/test/CodeGenObjC/objc-container-subscripting.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/objc-container-subscripting.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/objc-container-subscripting.m (added)
> +++ cfe/trunk/test/CodeGenObjC/objc-container-subscripting.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,45 @@
> +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin %s -o /dev/null
> +
> +typedef unsigned int size_t;
> + at protocol P @end
> +
> + at interface NSMutableArray
> +#if __has_feature(objc_subscripting)
> +- (id)objectAtIndexedSubscript:(size_t)index;
> +- (void)setObject:(id)object atIndexedSubscript:(size_t)index;
> +#endif
> + at end
> +
> +#if __has_feature(objc_subscripting)
> + at interface XNSMutableArray
> +- (id)objectAtIndexedSubscript:(size_t)index;
> +- (void)setObject:(id)object atIndexedSubscript:(size_t)index;
> +#endif
> + at end
> +
> + at interface NSMutableDictionary
> +- (id)objectForKeyedSubscript:(id)key;
> +- (void)setObject:(id)object forKeyedSubscript:(id)key;
> + at end
> +
> + at class NSString;
> +
> +int main() {
> + NSMutableArray<P> * array;
> + id oldObject = array[10];
> +
> + array[10] = oldObject;
> +
> + id unknown_array;
> + oldObject = unknown_array[1];
> +
> + unknown_array[1] = oldObject;
> +
> + NSMutableDictionary *dictionary;
> + NSString *key;
> + id newObject;
> + oldObject = dictionary[key];
> + dictionary[key] = newObject; // replace oldObject with newObject
> +
> +}
> +
>
> Added: cfe/trunk/test/CodeGenObjC/objc-dictionary-literal.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/objc-dictionary-literal.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/objc-dictionary-literal.m (added)
> +++ cfe/trunk/test/CodeGenObjC/objc-dictionary-literal.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,25 @@
> +// RUN: %clang_cc1 -x objective-c -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o /dev/null
> +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o /dev/null
> +// rdar://10614657
> +
> + at interface NSNumber
> ++ (NSNumber *)numberWithChar:(char)value;
> ++ (NSNumber *)numberWithInt:(int)value;
> + at end
> +
> + at protocol NSCopying @end
> +typedef unsigned long NSUInteger;
> +
> + at interface NSDictionary
> ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt;
> + at end
> +
> + at interface NSString<NSCopying>
> + at end
> +
> +int main() {
> + NSDictionary *dict = @{ @"name":@666 };
> + NSDictionary *dict1 = @{ @"name":@666 };
> + NSDictionary *dict2 = @{ @"name":@666 };
> + return 0;
> +}
>
> Added: cfe/trunk/test/CodeGenObjC/objc-literal-debugger-test.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/objc-literal-debugger-test.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/objc-literal-debugger-test.m (added)
> +++ cfe/trunk/test/CodeGenObjC/objc-literal-debugger-test.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,16 @@
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fdebugger-objc-literal -emit-llvm -o - %s | FileCheck %s
> +
> +int main() {
> + id l = @'a';
> + l = @'a';
> + l = @42;
> + l = @-42;
> + l = @42u;
> + l = @3.141592654f;
> + l = @__objc_yes;
> + l = @__objc_no;
> + l = @{ @"name":@666 };
> + l = @[ @"foo", @"bar" ];
> +}
> +
> +// CHECK: declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind
>
> Added: cfe/trunk/test/CodeGenObjC/objc-literal-tests.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/objc-literal-tests.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/objc-literal-tests.m (added)
> +++ cfe/trunk/test/CodeGenObjC/objc-literal-tests.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,95 @@
> +// RUN: %clang_cc1 -x objective-c -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o - | FileCheck %s
> +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o - | FileCheck %s
> +// rdar://10111397
> +
> +#if __has_feature(objc_bool)
> +#define YES __objc_yes
> +#define NO __objc_no
> +#else
> +#define YES ((BOOL)1)
> +#define NO ((BOOL)0)
> +#endif
> +
> +#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
> +typedef unsigned long NSUInteger;
> +typedef long NSInteger;
> +#else
> +typedef unsigned int NSUInteger;
> +typedef int NSInteger;
> +#endif
> +typedef signed char BOOL;
> +
> + at interface NSNumber @end
> +
> + at interface NSNumber (NSNumberCreation)
> +#if __has_feature(objc_array_literals)
> ++ (NSNumber *)numberWithChar:(char)value;
> ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
> ++ (NSNumber *)numberWithShort:(short)value;
> ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
> ++ (NSNumber *)numberWithInt:(int)value;
> ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
> ++ (NSNumber *)numberWithLong:(long)value;
> ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
> ++ (NSNumber *)numberWithLongLong:(long long)value;
> ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
> ++ (NSNumber *)numberWithFloat:(float)value;
> ++ (NSNumber *)numberWithDouble:(double)value;
> ++ (NSNumber *)numberWithBool:(BOOL)value;
> ++ (NSNumber *)numberWithInteger:(NSInteger)value ;
> ++ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value ;
> +#endif
> + at end
> +
> + at interface NSDate
> ++ (NSDate *) date;
> + at end
> +
> +#if __has_feature(objc_dictionary_literals)
> + at interface NSDictionary
> ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(NSUInteger)cnt;
> + at end
> +#endif
> +
> +id NSUserName();
> +
> +// CHECK: define i32 @main() nounwind
> +int main() {
> + // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 97
> + NSNumber *aNumber = @'a';
> + // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 42
> + NSNumber *fortyTwo = @42;
> + // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 -42
> + NSNumber *negativeFortyTwo = @-42;
> + // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 42
> + NSNumber *positiveFortyTwo = @+42;
> + // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 42
> + NSNumber *fortyTwoUnsigned = @42u;
> + // CHECK: call{{.*}}@objc_msgSend{{.*}}i64 42
> + NSNumber *fortyTwoLong = @42l;
> + // CHECK: call{{.*}}@objc_msgSend{{.*}}i64 42
> + NSNumber *fortyTwoLongLong = @42ll;
> + // CHECK: call{{.*}}@objc_msgSend{{.*}}float 0x400921FB60000000
> + NSNumber *piFloat = @3.141592654f;
> + // CHECK: call{{.*}}@objc_msgSend{{.*}}double 0x400921FB54411744
> + NSNumber *piDouble = @3.1415926535;
> + // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 1
> + NSNumber *yesNumber = @__objc_yes;
> + // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 0
> + NSNumber *noNumber = @__objc_no;
> + // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 1
> + NSNumber *yesNumber1 = @YES;
> + // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 0
> + NSNumber *noNumber1 = @NO;
> +NSDictionary *dictionary = @{@"name" : NSUserName(),
> + @"date" : [NSDate date] };
> + return __objc_yes == __objc_no;
> +}
> +
> +// rdar://10579122
> +typedef BOOL (^foo)(void);
> +extern void bar(foo a);
> +
> +void baz(void) {
> + bar(^(void) { return YES; });
> +}
>
> Added: cfe/trunk/test/CodeGenObjC/optimized-setter.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/optimized-setter.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/optimized-setter.m (added)
> +++ cfe/trunk/test/CodeGenObjC/optimized-setter.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,33 @@
> +// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-apple-macosx10.8.0 -o - | FileCheck %s
> +// rdar://10179974
> +
> + at interface I
> +// void objc_setProperty_nonatomic(id self, SEL _cmd, id newValue, ptrdiff_t offset);
> +// objc_setProperty(..., NO, NO)
> + at property (nonatomic, retain) id nonatomicProperty;
> +
> +// void objc_setProperty_nonatomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset);
> +// objc_setProperty(..., NO, YES)
> + at property (nonatomic, copy) id nonatomicPropertyCopy;
> +
> +// void objc_setProperty_atomic(id self, SEL _cmd, id newValue, ptrdiff_t offset);
> +// objc_setProperty(..., YES, NO)
> + at property (retain) id atomicProperty;
> +
> +// void objc_setProperty_atomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset);
> +// objc_setProperty(..., YES, YES)
> + at property (copy) id atomicPropertyCopy;
> + at end
> +
> + at implementation I
> + at synthesize nonatomicProperty;
> + at synthesize nonatomicPropertyCopy;
> + at synthesize atomicProperty;
> + at synthesize atomicPropertyCopy;
> + at end
> +
> +// CHECK: call void @objc_setProperty_nonatomic
> +// CHECK: call void @objc_setProperty_nonatomic_copy
> +// CHECK: call void @objc_setProperty_atomic
> +// CHECK: call void @objc_setProperty_atomic_copy
> +
>
> Added: cfe/trunk/test/CodeGenObjCXX/Inputs/literal-support.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/Inputs/literal-support.h?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjCXX/Inputs/literal-support.h (added)
> +++ cfe/trunk/test/CodeGenObjCXX/Inputs/literal-support.h Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,35 @@
> +#ifndef OBJC_LITERAL_SUPPORT_H
> +#define OBJC_LITERAL_SUPPORT_H
> +
> +typedef unsigned char BOOL;
> +
> + at interface NSNumber @end
> +
> + at interface NSNumber (NSNumberCreation)
> ++ (NSNumber *)numberWithChar:(char)value;
> ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
> ++ (NSNumber *)numberWithShort:(short)value;
> ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
> ++ (NSNumber *)numberWithInt:(int)value;
> ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
> ++ (NSNumber *)numberWithLong:(long)value;
> ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
> ++ (NSNumber *)numberWithLongLong:(long long)value;
> ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
> ++ (NSNumber *)numberWithFloat:(float)value;
> ++ (NSNumber *)numberWithDouble:(double)value;
> ++ (NSNumber *)numberWithBool:(BOOL)value;
> + at end
> +
> + at interface NSArray
> + at end
> +
> + at interface NSArray (NSArrayCreation)
> ++ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt;
> + at end
> +
> + at interface NSDictionary
> ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
> + at end
> +
> +#endif // OBJC_LITERAL_SUPPORT_H
>
> Added: cfe/trunk/test/CodeGenObjCXX/literals.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/literals.mm?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjCXX/literals.mm (added)
> +++ cfe/trunk/test/CodeGenObjCXX/literals.mm Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,111 @@
> +// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-arc-exceptions -O2 -disable-llvm-optzns -o - %s | FileCheck %s
> +
> +#include "literal-support.h"
> +
> +struct X {
> + X();
> + ~X();
> + operator id() const;
> +};
> +
> +struct Y {
> + Y();
> + ~Y();
> + operator id() const;
> +};
> +
> +// CHECK: define void @_Z10test_arrayv
> +void test_array() {
> + // CHECK: [[OBJECTS:%[a-zA-Z0-9.]+]] = alloca [2 x i8*]
> +
> + // Initializing first element
> + // CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 0
> + // CHECK-NEXT: call void @_ZN1XC1Ev
> + // CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv
> + // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT0]])
> + // CHECK: store i8* [[RET0]], i8** [[ELEMENT0]]
> +
> + // Initializing the second element
> + // CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1
> + // CHECK-NEXT: invoke void @_ZN1YC1Ev
> + // CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv
> + // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT1]])
> + // CHECK: store i8* [[RET1]], i8** [[ELEMENT1]]
> +
> + // Build the array
> + // CHECK: {{invoke.*@objc_msgSend}}
> + // CHECK: call i8* @objc_retainAutoreleasedReturnValue
> + id arr = @[ X(), Y() ];
> +
> + // Destroy temporaries
> + // CHECK-NOT: ret void
> + // CHECK: call void @objc_release
> + // CHECK-NOT: ret void
> + // CHECK: invoke void @_ZN1YD1Ev
> + // CHECK-NOT: ret void
> + // CHECK: call void @objc_release
> + // CHECK-NEXT: call void @_ZN1XD1Ev
> + // CHECK-NOT: ret void
> + // CHECK: call void @objc_release
> + // CHECK-NEXT: ret void
> +
> + // Check cleanups
> + // CHECK: call void @objc_release
> + // CHECK-NOT: call void @objc_release
> + // CHECK: invoke void @_ZN1YD1Ev
> + // CHECK: call void @objc_release
> + // CHECK-NOT: call void @objc_release
> + // CHECK: invoke void @_ZN1XD1Ev
> + // CHECK-NOT: call void @objc_release
> + // CHECK: unreachable
> +}
> +
> +// CHECK: define weak_odr void @_Z24test_array_instantiationIiEvv
> +template<typename T>
> +void test_array_instantiation() {
> + // CHECK: [[OBJECTS:%[a-zA-Z0-9.]+]] = alloca [2 x i8*]
> +
> + // Initializing first element
> + // CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 0
> + // CHECK-NEXT: call void @_ZN1XC1Ev
> + // CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv
> + // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT0]])
> + // CHECK: store i8* [[RET0]], i8** [[ELEMENT0]]
> +
> + // Initializing the second element
> + // CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1
> + // CHECK-NEXT: invoke void @_ZN1YC1Ev
> + // CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv
> + // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT1]])
> + // CHECK: store i8* [[RET1]], i8** [[ELEMENT1]]
> +
> + // Build the array
> + // CHECK: {{invoke.*@objc_msgSend}}
> + // CHECK: call i8* @objc_retainAutoreleasedReturnValue
> + id arr = @[ X(), Y() ];
> +
> + // Destroy temporaries
> + // CHECK-NOT: ret void
> + // CHECK: call void @objc_release
> + // CHECK-NOT: ret void
> + // CHECK: invoke void @_ZN1YD1Ev
> + // CHECK-NOT: ret void
> + // CHECK: call void @objc_release
> + // CHECK-NEXT: call void @_ZN1XD1Ev
> + // CHECK-NOT: ret void
> + // CHECK: call void @objc_release
> + // CHECK-NEXT: ret void
> +
> + // Check cleanups
> + // CHECK: call void @objc_release
> + // CHECK-NOT: call void @objc_release
> + // CHECK: invoke void @_ZN1YD1Ev
> + // CHECK: call void @objc_release
> + // CHECK-NOT: call void @objc_release
> + // CHECK: invoke void @_ZN1XD1Ev
> + // CHECK-NOT: call void @objc_release
> + // CHECK: unreachable
> +}
> +
> +template void test_array_instantiation<int>();
> +
>
> Added: cfe/trunk/test/CodeGenObjCXX/objc-container-subscripting-1.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/objc-container-subscripting-1.mm?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjCXX/objc-container-subscripting-1.mm (added)
> +++ cfe/trunk/test/CodeGenObjCXX/objc-container-subscripting-1.mm Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,50 @@
> +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s
> +
> +typedef unsigned int size_t;
> + at protocol P @end
> + at protocol NSCopying @end
> +
> + at interface NSMutableArray
> +- (id)objectAtIndexedSubscript:(size_t)index;
> +- (void)setObject:(id)object atIndexedSubscript:(size_t)index;
> + at end
> +
> +struct S {
> + operator unsigned int ();
> + operator id ();
> +};
> +
> + at interface NSMutableDictionary
> +- (id)objectForKeyedSubscript:(id<NSCopying>)key;
> +- (void)setObject:(id)object forKeyedSubscript:(id<NSCopying>)key;
> + at end
> +
> +int main() {
> + NSMutableArray<P> * array;
> + S s;
> + id oldObject = array[(int)s];
> +
> + NSMutableDictionary<P> *dict;
> + dict[(id)s] = oldObject;
> + oldObject = dict[(id)s];
> +
> +}
> +
> +template <class T> void test2(NSMutableArray *a) {
> + a[10] = 0;
> +}
> +template void test2<int>(NSMutableArray*);
> +// CHECK: define weak_odr void @_Z5test2IiEvP14NSMutableArray
> +// CHECK: @objc_msgSend
> +// CHECK: ret void
> +
> +
> +template <class T> void test3(NSMutableArray *a) {
> + a[sizeof(T)] = 0;
> +}
> +
> +template void test3<int>(NSMutableArray*);
> +// CHECK: define weak_odr void @_Z5test3IiEvP14NSMutableArray
> +// CHECK: @objc_msgSend
> +// CHECK: ret void
> +
>
> Added: cfe/trunk/test/CodeGenObjCXX/objc-container-subscripting.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/objc-container-subscripting.mm?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjCXX/objc-container-subscripting.mm (added)
> +++ cfe/trunk/test/CodeGenObjCXX/objc-container-subscripting.mm Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,57 @@
> +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s
> +
> +typedef unsigned int size_t;
> + at protocol P @end
> +
> + at interface NSMutableArray
> +- (id)objectAtIndexedSubscript:(size_t)index;
> +- (void)setObject:(id)object atIndexedSubscript:(size_t)index;
> + at end
> +
> +struct S {
> + operator unsigned int ();
> + operator id ();
> +};
> +
> + at interface NSMutableDictionary
> +- (id)objectForKeyedSubscript:(id)key;
> +- (void)setObject:(id)object forKeyedSubscript:(id)key;
> + at end
> +
> +int main() {
> + NSMutableArray<P> * array;
> + S s;
> + id oldObject = array[(int)s];
> +
> + NSMutableDictionary<P> *dict;
> + dict[(id)s] = oldObject;
> + oldObject = dict[(id)s];
> +
> +}
> +
> +template <class T> void test2(NSMutableArray *a) {
> + a[10] = 0;
> +}
> +template void test2<int>(NSMutableArray*);
> +// CHECK: define weak_odr void @_Z5test2IiEvP14NSMutableArray
> +// CHECK: @objc_msgSend
> +// CHECK: ret void
> +
> +
> +template <class T> void test3(NSMutableArray *a) {
> + a[sizeof(T)] = 0;
> +}
> +
> +template void test3<int>(NSMutableArray*);
> +// CHECK: define weak_odr void @_Z5test3IiEvP14NSMutableArray
> +// CHECK: @objc_msgSend
> +// CHECK: ret void
> +
> +// CHECK: define void @_Z11static_dataP14NSMutableArray
> +void static_data(NSMutableArray *array) {
> + // CHECK: call i32 @__cxa_guard_acquire
> + // CHECK: {{call i8*.*@objc_msgSend }}
> + // CHECK: call void @__cxa_guard_release
> + static id x = array[4];
> + // CHECK: ret void
> +}
>
> Added: cfe/trunk/test/Driver/arclite-link.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/arclite-link.c?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/Driver/arclite-link.c (added)
> +++ cfe/trunk/test/Driver/arclite-link.c Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,8 @@
> +// RUN: touch %t.o
> +// RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -mmacosx-version-min=10.7 %t.o 2>&1 | FileCheck -check-prefix=CHECK-ARCLITE-OSX %s
> +// RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -mmacosx-version-min=10.8 %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOARCLITE %s
> +// RUN: %clang -### -target i386-apple-darwin10 -fobjc-link-runtime -mmacosx-version-min=10.7 %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOARCLITE %s
> +
> +// CHECK-ARCLITE-OSX: libarclite_macosx.a
> +// CHECK-ARCLITE-OSX: -lobjc
> +// CHECK-NOARCLITE-NOT: libarclite
>
> Modified: cfe/trunk/test/Driver/darwin-ld.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/darwin-ld.c?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/test/Driver/darwin-ld.c (original)
> +++ cfe/trunk/test/Driver/darwin-ld.c Tue Mar 6 14:05:56 2012
> @@ -117,3 +117,7 @@
> // LINK_VERSION_MIN: "-macosx_version_min" "10.6.0"
> // LINK_VERSION_MIN: {{ld(.exe)?"}}
> // LINK_VERSION_MIN: "-macosx_version_min" "10.7.0"
> +
> +// RUN: %clang -target x86_64-apple-darwin12 -### %t.o 2> %t.log
> +// RUN: FileCheck -check-prefix=LINK_NO_CRT1 %s < %t.log
> +// LINK_NO_CRT1-NOT: crt
>
> Modified: cfe/trunk/test/Driver/rewrite-objc.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/rewrite-objc.m?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/test/Driver/rewrite-objc.m (original)
> +++ cfe/trunk/test/Driver/rewrite-objc.m Tue Mar 6 14:05:56 2012
> @@ -3,7 +3,7 @@
> // TEST0: clang{{.*}}" "-cc1"
> // TEST0: "-rewrite-objc"
> // FIXME: CHECK-NOT is broken somehow, it doesn't work here. Check adjacency instead.
> -// TEST0: "-fmessage-length" "0" "-stack-protector" "1" "-mstackrealign" "-fblocks" "-fobjc-runtime-has-arc" "-fobjc-runtime-has-weak" "-fobjc-fragile-abi" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fdiagnostics-show-option"
> +// TEST0: "-fmessage-length" "0" "-stack-protector" "1" "-mstackrealign" "-fblocks" "-fobjc-runtime-has-arc" "-fobjc-runtime-has-weak" "-fobjc-fragile-abi" "-fobjc-default-synthesize-properties" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fdiagnostics-show-option"
> // TEST0: rewrite-objc.m"
>
> // RUN: not %clang -ccc-no-clang -target unknown -rewrite-objc %s -o - -### 2>&1 | \
>
> Added: cfe/trunk/test/PCH/objc_container.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/objc_container.h?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/PCH/objc_container.h (added)
> +++ cfe/trunk/test/PCH/objc_container.h Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,26 @@
> + at protocol P @end
> +
> + at interface NSMutableArray
> +- (id)objectAtIndexedSubscript:(unsigned int)index;
> +- (void)setObject:(id)object atIndexedSubscript:(unsigned int)index;
> + at end
> +
> + at interface NSMutableDictionary
> +- (id)objectForKeyedSubscript:(id)key;
> +- (void)setObject:(id)object forKeyedSubscript:(id)key;
> + at end
> +
> +void all() {
> + NSMutableArray *array;
> + id oldObject = array[10];
> +
> + array[10] = oldObject;
> +
> + NSMutableDictionary *dictionary;
> + id key;
> + id newObject;
> + oldObject = dictionary[key];
> +
> + dictionary[key] = newObject;
> +}
> +
>
> Added: cfe/trunk/test/PCH/objc_container.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/objc_container.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/PCH/objc_container.m (added)
> +++ cfe/trunk/test/PCH/objc_container.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,20 @@
> +// Test this without pch.
> +// RUN: %clang_cc1 -include %S/objc_container.h -fsyntax-only -verify %s
> +
> +// Test with pch.
> +// RUN: %clang_cc1 -x objective-c -emit-pch -o %t %S/objc_container.h
> +// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s
> +// RUN: %clang -cc1 -include-pch %t -ast-print %s | FileCheck -check-prefix=PRINT %s
> +// RUN: %clang -cc1 -include-pch %t -emit-llvm -o - %s | FileCheck -check-prefix=IR %s
> +
> +// CHECK-PRINT: id oldObject = array[10];
> +// CHECK-PRINT: array[10] = oldObject;
> +// CHECK-PRINT: oldObject = dictionary[key];
> +// CHECK-PRINT: dictionary[key] = newObject;
> +
> +// CHECK-IR: define void @all() nounwind
> +// CHECK-IR: {{call.*objc_msgSend}}
> +// CHECK-IR: {{call.*objc_msgSend}}
> +// CHECK-IR: {{call.*objc_msgSend}}
> +// CHECK-IR: {{call.*objc_msgSend}}
> +// CHECK-IR: ret void
>
> Added: cfe/trunk/test/PCH/objc_literals.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/objc_literals.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/PCH/objc_literals.m (added)
> +++ cfe/trunk/test/PCH/objc_literals.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,66 @@
> +// RUN: %clang -cc1 -emit-pch -o %t %s
> +// RUN: %clang -cc1 -include-pch %t -verify %s
> +// RUN: %clang -cc1 -include-pch %t -ast-print %s | FileCheck -check-prefix=PRINT %s
> +// RUN: %clang -cc1 -include-pch %t -emit-llvm -o - %s | FileCheck -check-prefix=IR %s
> +
> +#ifndef HEADER
> +#define HEADER
> +
> +typedef unsigned char BOOL;
> +
> + at interface NSNumber @end
> +
> + at interface NSNumber (NSNumberCreation)
> ++ (NSNumber *)numberWithChar:(char)value;
> ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
> ++ (NSNumber *)numberWithShort:(short)value;
> ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
> ++ (NSNumber *)numberWithInt:(int)value;
> ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
> ++ (NSNumber *)numberWithLong:(long)value;
> ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
> ++ (NSNumber *)numberWithLongLong:(long long)value;
> ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
> ++ (NSNumber *)numberWithFloat:(float)value;
> ++ (NSNumber *)numberWithDouble:(double)value;
> ++ (NSNumber *)numberWithBool:(BOOL)value;
> + at end
> +
> + at interface NSArray
> + at end
> +
> + at interface NSArray (NSArrayCreation)
> ++ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt;
> + at end
> +
> + at interface NSDictionary
> ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
> + at end
> +
> +// CHECK-IR: define internal void @test_numeric_literals()
> +static inline void test_numeric_literals() {
> + // CHECK-PRINT: id intlit = @17
> + // CHECK-IR: {{call.*17}}
> + id intlit = @17;
> + // CHECK-PRINT: id floatlit = @17.45
> + // CHECK-IR: {{call.*1.745}}
> + id floatlit = @17.45;
> +}
> +
> +static inline void test_array_literals() {
> + // CHECK-PRINT: id arraylit = @[ @17, @17.45
> + id arraylit = @[@17, @17.45];
> +}
> +
> +static inline void test_dictionary_literals() {
> + // CHECK-PRINT: id dictlit = @{ @17 : {{@17.45[^,]*}}, @"hello" : @"world" };
> + id dictlit = @{@17 : @17.45, @"hello" : @"world" };
> +}
> +
> +#else
> +void test_all() {
> + test_numeric_literals();
> + test_array_literals();
> + test_dictionary_literals();
> +}
> +#endif
>
> Added: cfe/trunk/test/PCH/objc_literals.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/objc_literals.mm?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/PCH/objc_literals.mm (added)
> +++ cfe/trunk/test/PCH/objc_literals.mm Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,65 @@
> +// RUN: %clang -cc1 -emit-pch -x objective-c++ -std=c++0x -o %t %s
> +// RUN: %clang -cc1 -include-pch %t -x objective-c++ -std=c++0x -verify %s
> +// RUN: %clang -cc1 -include-pch %t -x objective-c++ -std=c++0x -ast-print %s | FileCheck -check-prefix=PRINT %s
> +// RUN: %clang -cc1 -include-pch %t -x objective-c++ -std=c++0x -emit-llvm -o - %s | FileCheck -check-prefix=IR %s
> +
> +#ifndef HEADER
> +#define HEADER
> +
> +typedef unsigned char BOOL;
> +
> + at interface NSNumber @end
> +
> + at interface NSNumber (NSNumberCreation)
> ++ (NSNumber *)numberWithChar:(char)value;
> ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
> ++ (NSNumber *)numberWithShort:(short)value;
> ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
> ++ (NSNumber *)numberWithInt:(int)value;
> ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
> ++ (NSNumber *)numberWithLong:(long)value;
> ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
> ++ (NSNumber *)numberWithLongLong:(long long)value;
> ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
> ++ (NSNumber *)numberWithFloat:(float)value;
> ++ (NSNumber *)numberWithDouble:(double)value;
> ++ (NSNumber *)numberWithBool:(BOOL)value;
> + at end
> +
> + at interface NSArray
> + at end
> +
> + at interface NSArray (NSArrayCreation)
> ++ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt;
> + at end
> +
> + at interface NSDictionary
> ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
> + at end
> +
> +template<typename T, typename U>
> +struct pair {
> + T first;
> + U second;
> +};
> +
> +template<typename T, typename U>
> +pair<T, U> make_pair(const T& first, const U& second) {
> + return { first, second };
> +}
> +
> +// CHECK-IR: define linkonce_odr void @_Z29variadic_dictionary_expansionIJP8NSStringS1_EJP8NSNumberS3_EEvDp4pairIT_T0_E
> +template<typename ...Ts, typename ... Us>
> +void variadic_dictionary_expansion(pair<Ts, Us>... key_values) {
> + // CHECK-PRINT: id dict = @{ key_values.first : key_values.second... };
> + // CHECK-IR: {{call.*objc_msgSend}}
> + // CHECK-IR: ret void
> + id dict = @{ key_values.first : key_values.second ... };
> +}
> +
> +#else
> +void test_all() {
> + variadic_dictionary_expansion(make_pair(@"Seventeen", @17),
> + make_pair(@"YES", @true));
> +}
> +#endif
>
> Added: cfe/trunk/test/PCH/subscripting-literals.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/subscripting-literals.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/PCH/subscripting-literals.m (added)
> +++ cfe/trunk/test/PCH/subscripting-literals.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,47 @@
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o %t.nopch.ll %s
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-pch -o %t.pch %s
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o %t.pch.ll %s -include-pch %t.pch
> +// RUN: diff %t.nopch.ll %t.pch.ll
> +
> +#ifndef HEADER
> +#define HEADER
> +
> + at interface NSArray
> +- (id)objectAtIndexedSubscript:(int)index;
> ++ (id)arrayWithObjects:(id *)objects count:(unsigned)count;
> + at end
> +
> + at interface NSMutableArray : NSArray
> +- (void)setObject:(id)object atIndexedSubscript:(int)index;
> + at end
> +
> + at interface NSDictionary
> +- (id)objectForKeyedSubscript:(id)key;
> ++ (id)dictionaryWithObjects:(id *)objects forKeys:(id *)keys count:(unsigned)count;
> + at end
> +
> + at interface NSMutableDictionary : NSDictionary
> +- (void)setObject:(id)object forKeyedSubscript:(id)key;
> + at end
> +
> + at interface NSNumber
> ++ (NSNumber *)numberWithInt:(int)value;
> + at end
> +
> + at class NSString;
> +
> +id testArray(int idx, id p) {
> + NSMutableArray *array;
> + array[idx] = p;
> + NSArray *arr = @[ p, @7 ];
> + return array[idx];
> +}
> +
> +void testDict(NSString *key, id newObject, id oldObject) {
> + NSMutableDictionary *dictionary;
> + oldObject = dictionary[key];
> + dictionary[key] = newObject;
> + NSDictionary *dict = @{ key: newObject, key: oldObject };
> +}
> +
> +#endif
>
> Added: cfe/trunk/test/SemaObjC/cocoa-api-usage.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/cocoa-api-usage.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/cocoa-api-usage.m (added)
> +++ cfe/trunk/test/SemaObjC/cocoa-api-usage.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,88 @@
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -fsyntax-only -Wobjc-cocoa-api -verify
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc %s -fsyntax-only -Wobjc-cocoa-api -verify
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -x objective-c %s.fixed -fsyntax-only
> +// RUN: cp %s %t.m
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %t.m -fixit -Wobjc-cocoa-api
> +// RUN: diff %s.fixed %t.m
> +// RUN: cp %s %t.m
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc %t.m -fixit -Wobjc-cocoa-api
> +// RUN: diff %s.fixed %t.m
> +
> +typedef signed char BOOL;
> +#define nil ((void*) 0)
> +
> + at interface NSObject
> ++ (id)alloc;
> + at end
> +
> + at interface NSString : NSObject
> ++ (id)stringWithString:(NSString *)string;
> +- (id)initWithString:(NSString *)aString;
> + at end
> +
> + at interface NSArray : NSObject
> +- (id)objectAtIndex:(unsigned long)index;
> +- (id)objectAtIndexedSubscript:(int)index;
> + at end
> +
> + at interface NSArray (NSArrayCreation)
> ++ (id)array;
> ++ (id)arrayWithObject:(id)anObject;
> ++ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt;
> ++ (id)arrayWithObjects:(id)firstObj, ...;
> ++ (id)arrayWithArray:(NSArray *)array;
> +
> +- (id)initWithObjects:(const id [])objects count:(unsigned long)cnt;
> +- (id)initWithObjects:(id)firstObj, ...;
> +- (id)initWithArray:(NSArray *)array;
> +
> +- (id)objectAtIndex:(unsigned long)index;
> + at end
> +
> + at interface NSMutableArray : NSArray
> +- (void)replaceObjectAtIndex:(unsigned long)index withObject:(id)anObject;
> +- (void)setObject:(id)object atIndexedSubscript:(int)index;
> + at end
> +
> + at interface NSDictionary : NSObject
> +- (id)objectForKeyedSubscript:(id)key;
> + at end
> +
> + at interface NSDictionary (NSDictionaryCreation)
> ++ (id)dictionary;
> ++ (id)dictionaryWithObject:(id)object forKey:(id)key;
> ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
> ++ (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...;
> ++ (id)dictionaryWithDictionary:(NSDictionary *)dict;
> ++ (id)dictionaryWithObjects:(NSArray *)objects forKeys:(NSArray *)keys;
> +
> +- (id)initWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
> +- (id)initWithObjectsAndKeys:(id)firstObject, ...;
> +- (id)initWithDictionary:(NSDictionary *)otherDictionary;
> +- (id)initWithObjects:(NSArray *)objects forKeys:(NSArray *)keys;
> +
> +- (id)objectForKey:(id)aKey;
> + at end
> +
> + at interface NSMutableDictionary : NSDictionary
> +- (void)setObject:(id)anObject forKey:(id)aKey;
> +- (void)setObject:(id)object forKeyedSubscript:(id)key;
> + at end
> +
> + at interface NSNumber : NSObject
> + at end
> +
> + at interface NSNumber (NSNumberCreation)
> ++ (NSNumber *)numberWithInt:(int)value;
> + at end
> +
> +#define M(x) (x)
> +#define PAIR(x) @#x, [NSNumber numberWithInt:(x)]
> +#define TWO(x) ((x), (x))
> +
> +void foo() {
> + NSString *str = M([NSString stringWithString:@"foo"]); // expected-warning {{redundant}}
> + str = [[NSString alloc] initWithString:@"foo"];
> + NSArray *arr = [NSArray arrayWithArray:@[str]]; // expected-warning {{redundant}}
> + NSDictionary *dict = [NSDictionary dictionaryWithDictionary:@{str: arr}]; // expected-warning {{redundant}}
> +}
>
> Added: cfe/trunk/test/SemaObjC/cocoa-api-usage.m.fixed
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/cocoa-api-usage.m.fixed?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/cocoa-api-usage.m.fixed (added)
> +++ cfe/trunk/test/SemaObjC/cocoa-api-usage.m.fixed Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,88 @@
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -fsyntax-only -Wobjc-cocoa-api -verify
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc %s -fsyntax-only -Wobjc-cocoa-api -verify
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -x objective-c %s.fixed -fsyntax-only
> +// RUN: cp %s %t.m
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %t.m -fixit -Wobjc-cocoa-api
> +// RUN: diff %s.fixed %t.m
> +// RUN: cp %s %t.m
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc %t.m -fixit -Wobjc-cocoa-api
> +// RUN: diff %s.fixed %t.m
> +
> +typedef signed char BOOL;
> +#define nil ((void*) 0)
> +
> + at interface NSObject
> ++ (id)alloc;
> + at end
> +
> + at interface NSString : NSObject
> ++ (id)stringWithString:(NSString *)string;
> +- (id)initWithString:(NSString *)aString;
> + at end
> +
> + at interface NSArray : NSObject
> +- (id)objectAtIndex:(unsigned long)index;
> +- (id)objectAtIndexedSubscript:(int)index;
> + at end
> +
> + at interface NSArray (NSArrayCreation)
> ++ (id)array;
> ++ (id)arrayWithObject:(id)anObject;
> ++ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt;
> ++ (id)arrayWithObjects:(id)firstObj, ...;
> ++ (id)arrayWithArray:(NSArray *)array;
> +
> +- (id)initWithObjects:(const id [])objects count:(unsigned long)cnt;
> +- (id)initWithObjects:(id)firstObj, ...;
> +- (id)initWithArray:(NSArray *)array;
> +
> +- (id)objectAtIndex:(unsigned long)index;
> + at end
> +
> + at interface NSMutableArray : NSArray
> +- (void)replaceObjectAtIndex:(unsigned long)index withObject:(id)anObject;
> +- (void)setObject:(id)object atIndexedSubscript:(int)index;
> + at end
> +
> + at interface NSDictionary : NSObject
> +- (id)objectForKeyedSubscript:(id)key;
> + at end
> +
> + at interface NSDictionary (NSDictionaryCreation)
> ++ (id)dictionary;
> ++ (id)dictionaryWithObject:(id)object forKey:(id)key;
> ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
> ++ (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...;
> ++ (id)dictionaryWithDictionary:(NSDictionary *)dict;
> ++ (id)dictionaryWithObjects:(NSArray *)objects forKeys:(NSArray *)keys;
> +
> +- (id)initWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
> +- (id)initWithObjectsAndKeys:(id)firstObject, ...;
> +- (id)initWithDictionary:(NSDictionary *)otherDictionary;
> +- (id)initWithObjects:(NSArray *)objects forKeys:(NSArray *)keys;
> +
> +- (id)objectForKey:(id)aKey;
> + at end
> +
> + at interface NSMutableDictionary : NSDictionary
> +- (void)setObject:(id)anObject forKey:(id)aKey;
> +- (void)setObject:(id)object forKeyedSubscript:(id)key;
> + at end
> +
> + at interface NSNumber : NSObject
> + at end
> +
> + at interface NSNumber (NSNumberCreation)
> ++ (NSNumber *)numberWithInt:(int)value;
> + at end
> +
> +#define M(x) (x)
> +#define PAIR(x) @#x, [NSNumber numberWithInt:(x)]
> +#define TWO(x) ((x), (x))
> +
> +void foo() {
> + NSString *str = M(@"foo"); // expected-warning {{redundant}}
> + str = [[NSString alloc] initWithString:@"foo"];
> + NSArray *arr = @[str]; // expected-warning {{redundant}}
> + NSDictionary *dict = @{str: arr}; // expected-warning {{redundant}}
> +}
>
> Modified: cfe/trunk/test/SemaObjC/invalid-code.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/invalid-code.m?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/invalid-code.m (original)
> +++ cfe/trunk/test/SemaObjC/invalid-code.m Tue Mar 6 14:05:56 2012
> @@ -2,7 +2,8 @@
>
> // rdar://6124613
> void test1() {
> - void *p = @1; // expected-error {{unexpected '@' in program}}
> + void *xyzzy = 0;
> + void *p = @xyzzy; // expected-error {{unexpected '@' in program}}
> }
>
> // <rdar://problem/7495713>
>
> Added: cfe/trunk/test/SemaObjC/objc-array-literal.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objc-array-literal.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/objc-array-literal.m (added)
> +++ cfe/trunk/test/SemaObjC/objc-array-literal.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,41 @@
> +// RUN: %clang_cc1 -fsyntax-only -verify %s
> +// rdar://10111397
> +
> +#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
> +typedef unsigned long NSUInteger;
> +#else
> +typedef unsigned int NSUInteger;
> +#endif
> +
> + at class NSString;
> +
> +extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
> +
> + at class NSFastEnumerationState;
> +
> + at protocol NSFastEnumeration
> +
> +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id [])buffer count:(NSUInteger)len;
> +
> + at end
> +
> + at interface NSNumber
> ++ (NSNumber *)numberWithInt:(int)value;
> + at end
> +
> + at interface NSArray <NSFastEnumeration>
> ++ (id)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
> + at end
> +
> +
> +int main() {
> + NSArray *array = @[@"Hello", @"There", @"How Are You", [NSNumber numberWithInt:42]];
> +
> + for (id string in array)
> + NSLog(@"%@\n", string);
> +
> + NSArray *array1 = @["Forgot"]; // expected-error {{string literal must be prefixed by '@' in a collection}}
> +
> + const char *blah;
> + NSArray *array2 = @[blah]; // expected-error{{collection element of type 'const char *' is not an Objective-C object}}
> +}
>
> Added: cfe/trunk/test/SemaObjC/objc-container-subscripting-1.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objc-container-subscripting-1.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/objc-container-subscripting-1.m (added)
> +++ cfe/trunk/test/SemaObjC/objc-container-subscripting-1.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,23 @@
> +// RUN: %clang_cc1 -fsyntax-only -verify %s
> +
> +typedef unsigned int size_t;
> + at protocol P @end
> +
> + at interface NSMutableArray
> + at end
> +
> + at interface XNSMutableArray
> + at end
> +
> +int main() {
> +id array;
> +id oldObject = array[10]; // expected-warning {{instance method '-objectAtIndexedSubscript:' not found (return type defaults to 'id')}}
> +
> +array[10] = 0; // expected-warning {{instance method '-setObject:atIndexedSubscript:' not found (return type defaults to 'id')}}
> +
> +id<P> p_array;
> +oldObject = p_array[10]; // expected-warning {{instance method '-objectAtIndexedSubscript:' not found (return type defaults to 'id')}}
> +
> +p_array[10] = 0; // expected-warning {{instance method '-setObject:atIndexedSubscript:' not found (return type defaults to 'id')}}
> +}
> +
>
> Added: cfe/trunk/test/SemaObjC/objc-container-subscripting-2.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objc-container-subscripting-2.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/objc-container-subscripting-2.m (added)
> +++ cfe/trunk/test/SemaObjC/objc-container-subscripting-2.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,30 @@
> +// RUN: %clang_cc1 -fsyntax-only -verify %s
> +
> +typedef unsigned int size_t;
> + at protocol P @end
> +
> + at interface NSMutableArray
> +- (id)objectAtIndexedSubscript:(size_t)index;
> +- (void)setObject:(id)object atIndexedSubscript:(size_t)index;
> + at end
> +
> + at interface NSMutableDictionary
> +- (id)objectForKeyedSubscript:(id)key;
> +- (void)setObject:(id)object forKeyedSubscript:(size_t)key;
> + at end
> +
> +id func() {
> + NSMutableArray *array;
> + float f;
> + array[f] = array; // expected-error {{expected method to write dictionary element not found on object of type 'NSMutableArray *'}}
> + return array[3.14]; // expected-error {{expected method to read dictionary element not found on object of type 'NSMutableArray *'}}
> +}
> +
> +void test_unused() {
> + NSMutableArray *array;
> + array[10]; // expected-warning {{container access result unused - container access should not be used for side effects}}
> +
> + NSMutableDictionary *dict;
> + dict[array]; // expected-warning {{container access result unused - container access should not be used for side effects}}
> +}
> +
>
> Added: cfe/trunk/test/SemaObjC/objc-container-subscripting-3.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objc-container-subscripting-3.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/objc-container-subscripting-3.m (added)
> +++ cfe/trunk/test/SemaObjC/objc-container-subscripting-3.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,25 @@
> +// RUN: %clang_cc1 -fsyntax-only -verify %s
> +// rdar://10904488
> +
> + at interface Test
> +- (int)objectAtIndexedSubscript:(int)index; // expected-note {{method 'objectAtIndexedSubscript:' declared here}}
> +- (void)setObject:(int)object atIndexedSubscript:(int)index; // expected-note {{parameter of type 'int' is declared here}}
> + at end
> +
> + at interface NSMutableDictionary
> +- (int)objectForKeyedSubscript:(id)key; // expected-note {{method 'objectForKeyedSubscript:' declared here}}
> +- (void)setObject:(int)object forKeyedSubscript:(id)key; // expected-note {{parameter of type 'int' is declared here}}
> + at end
> +
> +int main() {
> + Test *array;
> + int i = array[10]; // expected-error {{method for accessing array element must have Objective-C object return type instead of 'int'}}
> + array[2] = i; // expected-error {{cannot assign to this array because assigning method's 2nd parameter of type 'int' is not an objective-C pointer type}}
> +
> + NSMutableDictionary *dict;
> + id key, val;
> + val = dict[key]; // expected-error {{method for accessing dictionary element must have Objective-C object return type instead of 'int'}} \
> + // expected-warning {{incompatible integer to pointer conversion assigning to 'id' from 'int'}}
> + dict[key] = val; // expected-error {{method object parameter type 'int' is not object type}}
> +}
> +
>
> Added: cfe/trunk/test/SemaObjC/objc-container-subscripting.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objc-container-subscripting.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/objc-container-subscripting.m (added)
> +++ cfe/trunk/test/SemaObjC/objc-container-subscripting.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,42 @@
> +// RUN: %clang_cc1 -fsyntax-only -verify %s
> +
> +typedef unsigned int size_t;
> + at protocol P @end
> +
> + at interface NSMutableArray
> +- (id)objectAtIndexedSubscript:(double)index; // expected-note {{parameter of type 'double' is declared here}}
> +- (void)setObject:(id *)object atIndexedSubscript:(void *)index; // expected-note {{parameter of type 'void *' is declared here}} \
> + // expected-note {{parameter of type 'id *' is declared here}}
> + at end
> + at interface I @end
> +
> +int main() {
> + NSMutableArray<P> * array;
> + id oldObject = array[10]; // expected-error {{method index parameter type 'double' is not integral type}}
> + array[3] = 0; // expected-error {{method index parameter type 'void *' is not integral type}} \
> + // expected-error {{cannot assign to this array because assigning method's 2nd parameter of type 'id *' is not an objective-C pointer type}}
> +
> + I* iarray;
> + iarray[3] = 0; // expected-error {{expected method to write array element not found on object of type 'I *'}}
> + I* p = iarray[4]; // expected-error {{expected method to read array element not found on object of type 'I *'}}
> +
> + oldObject = array[10]++; // expected-error {{illegal operation on objective-c container subscripting}}
> + oldObject = array[10]--; // expected-error {{illegal operation on objective-c container subscripting}}
> + oldObject = --array[10]; // expected-error {{illegal operation on objective-c container subscripting}}
> +}
> +
> + at interface NSMutableDictionary
> +- (id)objectForKeyedSubscript:(id*)key; // expected-note {{parameter of type 'id *' is declared here}}
> +- (void)setObject:(void*)object forKeyedSubscript:(id*)key; // expected-note {{parameter of type 'void *' is declared here}} \
> + // expected-note {{parameter of type 'id *' is declared here}}
> + at end
> + at class NSString;
> +
> +void testDict() {
> + NSMutableDictionary *dictionary;
> + NSString *key;
> + id newObject, oldObject;
> + oldObject = dictionary[key]; // expected-error {{method key parameter type 'id *' is not object type}}
> + dictionary[key] = newObject; // expected-error {{method object parameter type 'void *' is not object type}} \
> + // expected-error {{method key parameter type 'id *' is not object type}}
> +}
>
> Added: cfe/trunk/test/SemaObjC/objc-literal-nsnumber.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objc-literal-nsnumber.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/objc-literal-nsnumber.m (added)
> +++ cfe/trunk/test/SemaObjC/objc-literal-nsnumber.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,78 @@
> +// RUN: %clang_cc1 -fsyntax-only -fblocks -verify %s
> +// rdar://10111397
> +
> +#if __LP64__
> +typedef unsigned long NSUInteger;
> +#else
> +typedef unsigned int NSUInteger;
> +#endif
> +
> + at interface NSObject
> ++ (NSObject*)nsobject;
> + at end
> +
> + at interface NSNumber : NSObject
> ++ (NSNumber *)numberWithChar:(char)value;
> ++ (NSNumber *)numberWithInt:(int)value;
> ++ (NSNumber *)numberWithFloat:(float)value;
> + at end
> +
> +int main() {
> + NSNumber * N = @3.1415926535; // expected-error {{declaration of 'numberWithDouble:' is missing in NSNumber class}}
> + NSNumber *noNumber = @__objc_yes; // expected-error {{declaration of 'numberWithBool:' is missing in NSNumber class}}
> + NSNumber * NInt = @1000;
> + NSNumber * NLongDouble = @1000.0l; // expected-error{{'long double' is not a valid literal type for NSNumber}}
> + id character = @ 'a';
> +
> + NSNumber *NNegativeInt = @-1000;
> + NSNumber *NPositiveInt = @+1000;
> + NSNumber *NNegativeFloat = @-1000.1f;
> + NSNumber *NPositiveFloat = @+1000.1f;
> +
> + int five = 5;
> + @-five; // expected-error{{@- must be followed by a number to form an NSNumber object}}
> + @+five; // expected-error{{@+ must be followed by a number to form an NSNumber object}}
> +}
> +
> +// Dictionary test
> + at class NSDictionary;
> +
> +NSDictionary *err() {
> + return @{@"name" : @"value"}; // expected-error {{declaration of 'dictionaryWithObjects:forKeys:count:' is missing in NSDictionary class}}
> +}
> +
> + at interface NSDate : NSObject
> ++ (NSDate *) date;
> + at end
> +
> + at protocol NSCopying
> +- copy;
> + at end
> +
> + at interface NSDictionary : NSObject
> ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id<NSCopying> [])keys count:(NSUInteger)cnt;
> + at end
> +
> + at interface NSString<NSCopying>
> + at end
> +
> +id NSUserName();
> +
> +int Int();
> +
> +NSDictionary * blocks() {
> + return @{ @"task" : ^ { return 17; } };
> +}
> +
> +NSDictionary * warn() {
> + NSDictionary *dictionary = @{@"name" : NSUserName(),
> + @"date" : [NSDate date],
> + @"name2" : @"other",
> + NSObject.nsobject : @"nsobject" }; // expected-warning{{passing 'NSObject *' to parameter of incompatible type 'const id<NSCopying>'}}
> + NSDictionary *dictionary2 = @{@"name" : Int()}; // expected-error {{collection element of type 'int' is not an Objective-C object}}
> +
> + NSObject *o;
> + NSDictionary *dictionary3 = @{o : o, // expected-warning{{passing 'NSObject *' to parameter of incompatible type 'const id<NSCopying>'}}
> + @"date" : [NSDate date] };
> + return dictionary3;
> +}
>
> Added: cfe/trunk/test/SemaObjC/objc-literal-sig.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objc-literal-sig.m?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/objc-literal-sig.m (added)
> +++ cfe/trunk/test/SemaObjC/objc-literal-sig.m Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,40 @@
> +// RUN: %clang_cc1 -fsyntax-only -verify %s
> +typedef _Bool BOOL;
> +
> + at interface NSNumber @end
> +
> + at interface NSNumber (NSNumberCreation)
> ++ (NSNumber *)numberWithChar:(char)value;
> ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
> ++ (NSNumber *)numberWithShort:(short)value;
> ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
> ++ (NSNumber *)numberWithInt:(int)value;
> ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
> ++ (NSNumber *)numberWithLong:(long)value;
> ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
> ++ (NSNumber *)numberWithLongLong:(long long)value;
> ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
> ++ (NSNumber *)numberWithFloat:(float)value;
> ++ (NSNumber *)numberWithDouble:(double)value;
> ++ (int)numberWithBool:(BOOL)value; // expected-note{{method returns unexpected type 'int' (should be an object type)}}
> + at end
> +
> + at interface NSArray
> + at end
> +
> + at interface NSArray (NSArrayCreation)
> ++ (id)arrayWithObjects:(const int [])objects // expected-note{{first parameter has unexpected type 'const int *' (should be 'const id *')}}
> + count:(unsigned long)cnt;
> + at end
> +
> + at interface NSDictionary
> ++ (id)dictionaryWithObjects:(const id [])objects
> + forKeys:(const int [])keys // expected-note{{second parameter has unexpected type 'const int *' (should be 'const id *')}}
> + count:(unsigned long)cnt;
> + at end
> +
> +void test_sig() {
> + (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
> + id array = @[ @17 ]; // expected-error{{literal construction method 'arrayWithObjects:count:' has incompatible signature}}
> + id dict = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible signature}}
> +}
>
> Modified: cfe/trunk/test/SemaObjC/sizeof-interface.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/sizeof-interface.m?rev=152137&r1=152136&r2=152137&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/sizeof-interface.m (original)
> +++ cfe/trunk/test/SemaObjC/sizeof-interface.m Tue Mar 6 14:05:56 2012
> @@ -1,6 +1,6 @@
> // RUN: %clang_cc1 -verify -fsyntax-only %s
>
> - at class I0; // expected-note 3{{forward declaration of class here}}
> + at class I0; // expected-note 2{{forward declaration of class here}}
>
> // rdar://6811884
> int g0 = sizeof(I0); // expected-error{{invalid application of 'sizeof' to an incomplete type 'I0'}}
> @@ -9,7 +9,7 @@
> void *g3(I0 *P) {
> P = P+5; // expected-error {{arithmetic on a pointer to an incomplete type 'I0'}}
>
> - return &P[4]; // expected-error{{subscript of pointer to incomplete type 'I0'}}
> + return &P[4]; // expected-error{{expected method to read array element not found on object of type 'I0 *'}}
> }
>
>
> @@ -55,7 +55,7 @@
> P = 5+P; // expected-error {{arithmetic on pointer to interface 'I0', which is not a constant size in non-fragile ABI}}
> P = P-5; // expected-error {{arithmetic on pointer to interface 'I0', which is not a constant size in non-fragile ABI}}
>
> - return P[4].x[2]; // expected-error {{subscript requires size of interface 'I0', which is not constant in non-fragile ABI}}
> + return P[4].x[2]; // expected-error {{expected method to read array element not found on object of type 'I0 *'}}
> }
>
>
>
> Added: cfe/trunk/test/SemaObjCXX/literals.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/literals.mm?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/literals.mm (added)
> +++ cfe/trunk/test/SemaObjCXX/literals.mm Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,178 @@
> +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x -fblocks %s
> +
> +typedef unsigned char BOOL;
> +
> + at protocol NSCopying
> +- copy;
> + at end
> +
> + at interface NSObject
> + at end
> +
> + at interface NSNumber : NSObject <NSCopying>
> +-copy;
> + at end
> +
> + at interface NSNumber (NSNumberCreation)
> ++ (NSNumber *)numberWithChar:(char)value;
> ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
> ++ (NSNumber *)numberWithShort:(short)value;
> ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
> ++ (NSNumber *)numberWithInt:(int)value;
> ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
> ++ (NSNumber *)numberWithLong:(long)value;
> ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
> ++ (NSNumber *)numberWithLongLong:(long long)value;
> ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
> ++ (NSNumber *)numberWithFloat:(float)value;
> ++ (NSNumber *)numberWithDouble:(double)value;
> ++ (NSNumber *)numberWithBool:(BOOL)value;
> + at end
> +
> + at interface NSArray : NSObject <NSCopying>
> +-copy;
> + at end
> +
> + at interface NSArray (NSArrayCreation)
> ++ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt;
> + at end
> +
> + at interface NSDictionary
> ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id<NSCopying> [])keys count:(unsigned long)cnt;
> + at end
> +
> +template<typename T>
> +struct ConvertibleTo {
> + operator T();
> +};
> +
> +template<typename T>
> +struct ExplicitlyConvertibleTo {
> + explicit operator T();
> +};
> +
> +template<typename T>
> +class PrivateConvertibleTo {
> +private:
> + operator T(); // expected-note{{declared private here}}
> +};
> +
> +template<typename T> ConvertibleTo<T> makeConvertible();
> +
> +struct X {
> + ConvertibleTo<id> x;
> + ConvertibleTo<id> get();
> +};
> +
> +template<typename T> T test_numeric_instantiation() {
> + return @-17.42;
> +}
> +
> +template id test_numeric_instantiation();
> +
> +void test_convertibility(ConvertibleTo<NSArray*> toArray,
> + ConvertibleTo<id> toId,
> + ConvertibleTo<int (^)(int)> toBlock,
> + ConvertibleTo<int> toInt,
> + ExplicitlyConvertibleTo<NSArray *> toArrayExplicit) {
> + id array = @[
> + toArray,
> + toId,
> + toBlock,
> + toInt // expected-error{{collection element of type 'ConvertibleTo<int>' is not an Objective-C object}}
> + ];
> + id array2 = @[ toArrayExplicit ]; // expected-error{{collection element of type 'ExplicitlyConvertibleTo<NSArray *>' is not an Objective-C object}}
> +
> + id array3 = @[
> + makeConvertible<id>(),
> + makeConvertible<id>, // expected-error{{collection element of type 'ConvertibleTo<id> ()' is not an Objective-C object}}
> + ];
> +
> + X x;
> + id array4 = @[ x.x ];
> + id array5 = @[ x.get ]; // expected-error{{reference to non-static member function must be called}}
> + id array6 = @[ PrivateConvertibleTo<NSArray*>() ]; // expected-error{{operator NSArray *' is a private member of 'PrivateConvertibleTo<NSArray *>'}}
> +}
> +
> +template<typename T>
> +void test_array_literals(T t) {
> + id arr = @[ @17, t ]; // expected-error{{collection element of type 'int' is not an Objective-C object}}
> +}
> +
> +template void test_array_literals(id);
> +template void test_array_literals(NSArray*);
> +template void test_array_literals(int); // expected-note{{in instantiation of function template specialization 'test_array_literals<int>' requested here}}
> +
> +template<typename T, typename U>
> +void test_dictionary_literals(T t, U u) {
> + NSObject *object;
> + id dict = @{
> + @17 : t, // expected-error{{collection element of type 'int' is not an Objective-C object}}
> + u : @42 // expected-error{{collection element of type 'int' is not an Objective-C object}}
> + };
> +
> + id dict2 = @{
> + object : @"object" // expected-error{{cannot initialize a parameter of type 'const id<NSCopying>' with an rvalue of type 'NSObject *'}}
> + };
> +}
> +
> +template void test_dictionary_literals(id, NSArray*);
> +template void test_dictionary_literals(NSArray*, id);
> +template void test_dictionary_literals(int, id); // expected-note{{in instantiation of function template specialization 'test_dictionary_literals<int, id>' requested here}}
> +template void test_dictionary_literals(id, int); // expected-note{{in instantiation of function template specialization 'test_dictionary_literals<id, int>' requested here}}
> +
> +template<typename ...Args>
> +void test_bad_variadic_array_literal(Args ...args) {
> + id arr1 = @[ args ]; // expected-error{{initializer contains unexpanded parameter pack 'args'}}
> +}
> +
> +template<typename ...Args>
> +void test_variadic_array_literal(Args ...args) {
> + id arr1 = @[ args... ]; // expected-error{{collection element of type 'int' is not an Objective-C object}}
> +}
> +template void test_variadic_array_literal(id);
> +template void test_variadic_array_literal(id, NSArray*);
> +template void test_variadic_array_literal(id, int, NSArray*); // expected-note{{in instantiation of function template specialization 'test_variadic_array_literal<id, int, NSArray *>' requested here}}
> +
> +template<typename ...Args>
> +void test_bad_variadic_dictionary_literal(Args ...args) {
> + id dict = @{ args : @17 }; // expected-error{{initializer contains unexpanded parameter pack 'args'}}
> +}
> +
> +// Test array literal pack expansions.
> +template<typename T, typename U>
> +struct pair {
> + T first;
> + U second;
> +};
> +
> +template<typename T, typename ...Ts, typename ... Us>
> +void test_variadic_dictionary_expansion(T t, pair<Ts, Us>... key_values) {
> + id dict = @{
> + t : key_values.second ..., // expected-error{{collection element of type 'int' is not an Objective-C object}}
> + key_values.first : key_values.second ..., // expected-error{{collection element of type 'float' is not an Objective-C object}}
> + key_values.second : t ...
> + };
> +}
> +
> +template void test_variadic_dictionary_expansion(id,
> + pair<NSNumber*, id>,
> + pair<id, ConvertibleTo<id>>);
> +template void test_variadic_dictionary_expansion(NSNumber *, // expected-note{{in instantiation of function template specialization}}
> + pair<NSNumber*, int>,
> + pair<id, ConvertibleTo<id>>);
> +template void test_variadic_dictionary_expansion(NSNumber *, // expected-note{{in instantiation of function template specialization}}
> + pair<NSNumber*, id>,
> + pair<float, ConvertibleTo<id>>);
> +
> +// Test parsing
> +struct key {
> + static id value;
> +};
> +
> +id key;
> +id value;
> +
> +void test_dictionary_colon() {
> + id dict = @{ key : value };
> +}
>
> Added: cfe/trunk/test/SemaObjCXX/objc-container-subscripting.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/objc-container-subscripting.mm?rev=152137&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/objc-container-subscripting.mm (added)
> +++ cfe/trunk/test/SemaObjCXX/objc-container-subscripting.mm Tue Mar 6 14:05:56 2012
> @@ -0,0 +1,138 @@
> +// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin11 -fsyntax-only -std=c++11 -verify %s
> +
> + at class NSArray;
> +
> + at interface NSMutableDictionary
> +- (id)objectForKeyedSubscript:(id)key;
> +- (void)setObject:(id)object forKeyedSubscript:(id)key; // expected-note {{passing argument to parameter 'object' here}}
> + at end
> +
> +template<typename T, typename U, typename O>
> +void test_dictionary_subscripts(T base, U key, O obj) {
> + base[key] = obj; // expected-error {{expected method to write array element not found on object of type 'NSMutableDictionary *'}} \
> + // expected-error {{cannot initialize a parameter of type 'id' with an lvalue of type 'int'}}
> + obj = base[key]; // expected-error {{expected method to read array element not found on object of type 'NSMutableDictionary *'}} \
> + // expected-error {{assigning to 'int' from incompatible type 'id'}}
> +
> +}
> +
> +template void test_dictionary_subscripts(NSMutableDictionary*, id, NSArray *ns);
> +
> +template void test_dictionary_subscripts(NSMutableDictionary*, NSArray *ns, id);
> +
> +template void test_dictionary_subscripts(NSMutableDictionary*, int, id); // expected-note {{in instantiation of function template specialization 'test_dictionary_subscripts<NSMutableDictionary *, int, id>' requested here}}
> +
> +template void test_dictionary_subscripts(NSMutableDictionary*, id, int); // expected-note {{in instantiation of function template specialization 'test_dictionary_subscripts<NSMutableDictionary *, id, int>' requested here}}
> +
> +
> + at interface NSMutableArray
> +- (id)objectAtIndexedSubscript:(int)index;
> +- (void)setObject:(id)object atIndexedSubscript:(int)index;
> + at end
> +
> +template<typename T, typename U, typename O>
> +void test_array_subscripts(T base, U index, O obj) {
> + base[index] = obj; // expected-error {{expected method to write dictionary element not found on object of type 'NSMutableArray *'}}
> + obj = base[index]; // expected-error {{expected method to read dictionary element not found on object of type 'NSMutableArray *'}}
> +}
> +
> +template void test_array_subscripts(NSMutableArray *, int, id);
> +template void test_array_subscripts(NSMutableArray *, short, id);
> +enum E { e };
> +
> +template void test_array_subscripts(NSMutableArray *, E, id);
> +
> +template void test_array_subscripts(NSMutableArray *, double, id); // expected-note {{in instantiation of function template specialization 'test_array_subscripts<NSMutableArray *, double, id>' requested here}}
> +
> +template<typename T>
> +struct ConvertibleTo {
> + operator T();
> +};
> +
> +template<typename T>
> +struct ExplicitlyConvertibleTo {
> + explicit operator T();
> +};
> +
> +template<typename T> ConvertibleTo<T> makeConvertible();
> +
> +struct X {
> + ConvertibleTo<id> x;
> + ConvertibleTo<id> get();
> +};
> +
> +NSMutableArray *test_array_convertibility(ConvertibleTo<NSMutableArray*> toArray,
> + ConvertibleTo<id> toId,
> + ConvertibleTo<int (^)(int)> toBlock,
> + ConvertibleTo<int> toInt,
> + ExplicitlyConvertibleTo<NSMutableArray *> toArrayExplicit) {
> + id array;
> +
> + array[1] = toArray;
> +
> + array[4] = array[1];
> +
> + toArrayExplicit[2] = toId; // expected-error {{type 'ExplicitlyConvertibleTo<NSMutableArray *>' does not provide a subscript operator}}
> +
> + return array[toInt];
> +
> +}
> +
> +id test_dict_convertibility(ConvertibleTo<NSMutableDictionary*> toDict,
> + ConvertibleTo<id> toId,
> + ConvertibleTo<int (^)(int)> toBlock,
> + ConvertibleTo<int> toInt,
> + ExplicitlyConvertibleTo<NSMutableDictionary *> toDictExplicit) {
> +
> +
> + NSMutableDictionary *Dict;
> + id Id;
> + Dict[toId] = toBlock;
> +
> + Dict[toBlock] = toBlock;
> +
> + Dict[toBlock] = Dict[toId] = Dict[toBlock];
> +
> + Id = toDictExplicit[toId] = Id; // expected-error {{no viable overloaded operator[] for type 'ExplicitlyConvertibleTo<NSMutableDictionary *>'}}
> +
> + return Dict[toBlock];
> +}
> +
> +
> +template<typename ...Args>
> +void test_bad_variadic_array_subscripting(Args ...args) {
> + id arr1;
> + arr1[3] = args; // expected-error {{expression contains unexpanded parameter pack 'args'}}
> +}
> +
> +template<typename ...Args>
> +void test_variadic_array_subscripting(Args ...args) {
> + id arr[] = {args[3]...}; // which means: {a[3], b[3], c[3]};
> +}
> +
> +template void test_variadic_array_subscripting(id arg1, NSMutableArray* arg2, id arg3);
> +
> + at class Key;
> +
> +template<typename Index, typename ...Args>
> +void test_variadic_dictionary_subscripting(Index I, Args ...args) {
> + id arr[] = {args[I]...}; // which means: {a[3], b[3], c[3]};
> +}
> +
> +template void test_variadic_dictionary_subscripting(Key *key, id arg1, NSMutableDictionary* arg2, id arg3);
> +
> +template<int N>
> +id get(NSMutableArray *array) {
> + return array[N]; // array[N] should be a value- and instantiation-dependent ObjCSubscriptRefExpr
> +}
> +
> +struct WeirdIndex {
> + operator int(); // expected-note {{type conversion function declared here}}
> + operator id(); // expected-note {{type conversion function declared here}}
> +};
> +
> +id FUNC(WeirdIndex w) {
> + NSMutableArray *array;
> + return array[w]; // expected-error {{indexing expression is invalid because subscript type 'WeirdIndex' has multiple type conversion functions}}
> +}
> +
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list