llvm-project/clang/lib/Parse/AttributeList.cpp

128 lines
4.8 KiB
C++
Raw Normal View History

//===--- AttributeList.cpp --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the AttributeList class implementation
//
//===----------------------------------------------------------------------===//
#include "clang/Parse/AttributeList.h"
using namespace clang;
AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
IdentifierInfo *pName, SourceLocation pLoc,
Action::ExprTy **elist, unsigned numargs,
AttributeList *n)
: AttrName(aName), AttrLoc(aLoc), ParmName(pName), ParmLoc(pLoc),
NumArgs(numargs), Next(n) {
Args = new Action::ExprTy*[numargs];
for (unsigned i = 0; i != numargs; ++i)
Args[i] = elist[i];
}
AttributeList::~AttributeList() {
if (Args) {
// FIXME: before we delete the vector, we need to make sure the Expr's
// have been deleted. Since Action::ExprTy is "void", we are dependent
// on the actions module for actually freeing the memory. The specific
// hooks are ActOnDeclarator, ActOnTypeName, ActOnParamDeclaratorType,
// ParseField, ParseTag. Once these routines have freed the expression,
// they should zero out the Args slot (to indicate the memory has been
// freed). If any element of the vector is non-null, we should assert.
delete [] Args;
}
delete Next;
}
AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
const char *Str = Name->getName();
unsigned Len = Name->getLength();
// Normalize the attribute name, __foo__ becomes foo.
if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
Str[Len - 2] == '_' && Str[Len - 1] == '_') {
Str += 2;
Len -= 4;
}
// FIXME: Hand generating this is neither smart nor efficient.
switch (Len) {
case 4:
if (!memcmp(Str, "weak", 4)) return AT_weak;
if (!memcmp(Str, "pure", 4)) return AT_pure;
if (!memcmp(Str, "mode", 4)) return AT_mode;
if (!memcmp(Str, "used", 4)) return AT_used;
break;
case 5:
if (!memcmp(Str, "alias", 5)) return AT_alias;
if (!memcmp(Str, "const", 5)) return AT_const;
break;
case 6:
if (!memcmp(Str, "packed", 6)) return AT_packed;
if (!memcmp(Str, "malloc", 6)) return IgnoredAttribute;
if (!memcmp(Str, "format", 6)) return AT_format;
if (!memcmp(Str, "unused", 6)) return AT_unused;
if (!memcmp(Str, "blocks", 6)) return AT_blocks;
break;
case 7:
if (!memcmp(Str, "aligned", 7)) return AT_aligned;
if (!memcmp(Str, "cleanup", 7)) return AT_cleanup;
if (!memcmp(Str, "nodebug", 7)) return AT_nodebug;
if (!memcmp(Str, "nonnull", 7)) return AT_nonnull;
if (!memcmp(Str, "nothrow", 7)) return AT_nothrow;
if (!memcmp(Str, "objc_gc", 7)) return AT_objc_gc;
if (!memcmp(Str, "section", 7)) return AT_section;
if (!memcmp(Str, "stdcall", 7)) return AT_stdcall;
break;
case 8:
if (!memcmp(Str, "annotate", 8)) return AT_annotate;
if (!memcmp(Str, "noreturn", 8)) return AT_noreturn;
if (!memcmp(Str, "noinline", 8)) return AT_noinline;
if (!memcmp(Str, "fastcall", 8)) return AT_fastcall;
if (!memcmp(Str, "iboutlet", 8)) return AT_IBOutlet;
if (!memcmp(Str, "sentinel", 8)) return AT_sentinel;
if (!memcmp(Str, "NSObject", 8)) return AT_nsobject;
break;
case 9:
if (!memcmp(Str, "dllimport", 9)) return AT_dllimport;
if (!memcmp(Str, "dllexport", 9)) return AT_dllexport;
if (!memcmp(Str, "may_alias", 9)) return IgnoredAttribute;
break;
case 10:
if (!memcmp(Str, "deprecated", 10)) return AT_deprecated;
if (!memcmp(Str, "visibility", 10)) return AT_visibility;
if (!memcmp(Str, "destructor", 10)) return AT_destructor;
break;
case 11:
if (!memcmp(Str, "vector_size", 11)) return AT_vector_size;
if (!memcmp(Str, "constructor", 11)) return AT_constructor;
if (!memcmp(Str, "unavailable", 11)) return AT_unavailable;
break;
Initial implementation of function overloading in C. This commit adds a new attribute, "overloadable", that enables C++ function overloading in C. The attribute can only be added to function declarations, e.g., int *f(int) __attribute__((overloadable)); If the "overloadable" attribute exists on a function with a given name, *all* functions with that name (and in that scope) must have the "overloadable" attribute. Sets of overloaded functions with the "overloadable" attribute then follow the normal C++ rules for overloaded functions, e.g., overloads must have different parameter-type-lists from each other. When calling an overloaded function in C, we follow the same overloading rules as C++, with three extensions to the set of standard conversions: - A value of a given struct or union type T can be converted to the type T. This is just the identity conversion. (In C++, this would go through a copy constructor). - A value of pointer type T* can be converted to a value of type U* if T and U are compatible types. This conversion has Conversion rank (it's considered a pointer conversion in C). - A value of type T can be converted to a value of type U if T and U are compatible (and are not both pointer types). This conversion has Conversion rank (it's considered to be a new kind of conversion unique to C, a "compatible" conversion). Known defects (and, therefore, next steps): 1) The standard-conversion handling does not understand conversions involving _Complex or vector extensions, so it is likely to get these wrong. We need to add these conversions. 2) All overloadable functions with the same name will have the same linkage name, which means we'll get a collision in the linker (if not sooner). We'll need to mangle the names of these functions. llvm-svn: 64336
2009-02-12 07:02:49 +08:00
case 12:
if (!memcmp(Str, "overloadable", 12)) return AT_overloadable;
break;
case 13:
if (!memcmp(Str, "address_space", 13)) return AT_address_space;
if (!memcmp(Str, "always_inline", 13)) return AT_always_inline;
break;
case 15:
if (!memcmp(Str, "ext_vector_type", 15)) return AT_ext_vector_type;
break;
case 16:
if (!memcmp(Str, "warnunusedresult", 16)) return AT_warn_unused_result;
break;
case 17:
if (!memcmp(Str, "transparent_union", 17)) return AT_transparent_union;
break;
case 18:
if (!memcmp(Str, "warn_unused_result", 18)) return AT_warn_unused_result;
break;
}
return UnknownAttribute;
}