hanchenye-llvm-project/clang/lib/AST/DeclBase.cpp

750 lines
22 KiB
C++
Raw Normal View History

//===--- DeclBase.cpp - Declaration AST Node Implementation ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Decl and DeclContext classes.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/DeclBase.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace clang;
//===----------------------------------------------------------------------===//
// Statistics
//===----------------------------------------------------------------------===//
#define DECL(Derived, Base) static int n##Derived##s = 0;
#include "clang/AST/DeclNodes.def"
static bool StatSwitch = false;
const char *Decl::getDeclKindName() const {
switch (DeclKind) {
default: assert(0 && "Declaration not in DeclNodes.def!");
#define DECL(Derived, Base) case Derived: return #Derived;
#include "clang/AST/DeclNodes.def"
}
}
const char *DeclContext::getDeclKindName() const {
switch (DeclKind) {
default: assert(0 && "Declaration context not in DeclNodes.def!");
#define DECL(Derived, Base) case Decl::Derived: return #Derived;
#include "clang/AST/DeclNodes.def"
}
}
bool Decl::CollectingStats(bool Enable) {
if (Enable)
StatSwitch = true;
return StatSwitch;
}
void Decl::PrintStats() {
fprintf(stderr, "*** Decl Stats:\n");
int totalDecls = 0;
#define DECL(Derived, Base) totalDecls += n##Derived##s;
#include "clang/AST/DeclNodes.def"
fprintf(stderr, " %d decls total.\n", totalDecls);
int totalBytes = 0;
#define DECL(Derived, Base) \
if (n##Derived##s > 0) { \
totalBytes += (int)(n##Derived##s * sizeof(Derived##Decl)); \
fprintf(stderr, " %d " #Derived " decls, %d each (%d bytes)\n", \
n##Derived##s, (int)sizeof(Derived##Decl), \
(int)(n##Derived##s * sizeof(Derived##Decl))); \
}
#include "clang/AST/DeclNodes.def"
fprintf(stderr, "Total bytes = %d\n", totalBytes);
}
void Decl::addDeclKind(Kind k) {
switch (k) {
default: assert(0 && "Declaration not in DeclNodes.def!");
#define DECL(Derived, Base) case Derived: ++n##Derived##s; break;
#include "clang/AST/DeclNodes.def"
}
}
bool Decl::isTemplateParameterPack() const {
if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(this))
return TTP->isParameterPack();
return false;
}
bool Decl::isFunctionOrFunctionTemplate() const {
return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this);
}
//===----------------------------------------------------------------------===//
// PrettyStackTraceDecl Implementation
//===----------------------------------------------------------------------===//
void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
SourceLocation TheLoc = Loc;
if (TheLoc.isInvalid() && TheDecl)
TheLoc = TheDecl->getLocation();
if (TheLoc.isValid()) {
TheLoc.print(OS, SM);
OS << ": ";
}
OS << Message;
if (NamedDecl *DN = dyn_cast_or_null<NamedDecl>(TheDecl))
OS << " '" << DN->getQualifiedNameAsString() << '\'';
OS << '\n';
}
//===----------------------------------------------------------------------===//
// Decl Implementation
//===----------------------------------------------------------------------===//
// Out-of-line virtual method providing a home for Decl.
Decl::~Decl() {
if (isOutOfSemaDC())
delete getMultipleDC();
assert(!HasAttrs && "attributes should have been freed by Destroy");
}
void Decl::setDeclContext(DeclContext *DC) {
if (isOutOfSemaDC())
delete getMultipleDC();
DeclCtx = DC;
}
void Decl::setLexicalDeclContext(DeclContext *DC) {
if (DC == getLexicalDeclContext())
return;
if (isInSemaDC()) {
MultipleDC *MDC = new MultipleDC();
MDC->SemanticDC = getDeclContext();
MDC->LexicalDC = DC;
DeclCtx = MDC;
} else {
getMultipleDC()->LexicalDC = DC;
}
}
unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
switch (DeclKind) {
default:
if (DeclKind >= FunctionFirst && DeclKind <= FunctionLast)
return IDNS_Ordinary;
assert(0 && "Unknown decl kind!");
case OverloadedFunction:
case Typedef:
case EnumConstant:
case Var:
case ImplicitParam:
case ParmVar:
case OriginalParmVar:
case NonTypeTemplateParm:
case Using:
case ObjCMethod:
case ObjCContainer:
case ObjCCategory:
case ObjCInterface:
case ObjCProperty:
case ObjCCompatibleAlias:
return IDNS_Ordinary;
case ObjCProtocol:
return IDNS_ObjCProtocol;
case ObjCImplementation:
return IDNS_ObjCImplementation;
case ObjCCategoryImpl:
return IDNS_ObjCCategoryImpl;
case Field:
case ObjCAtDefsField:
case ObjCIvar:
return IDNS_Member;
case Record:
case CXXRecord:
case Enum:
case TemplateTypeParm:
return IDNS_Tag;
case Namespace:
case Template:
case FunctionTemplate:
case ClassTemplate:
case TemplateTemplateParm:
case NamespaceAlias:
return IDNS_Tag | IDNS_Ordinary;
// Never have names.
case LinkageSpec:
case FileScopeAsm:
case StaticAssert:
case ObjCClass:
case ObjCPropertyImpl:
case ObjCForwardProtocol:
case Block:
case TranslationUnit:
// Aren't looked up?
case UsingDirective:
case ClassTemplateSpecialization:
case ClassTemplatePartialSpecialization:
return 0;
}
}
void Decl::addAttr(ASTContext &Context, Attr *NewAttr) {
Attr *&ExistingAttr = Context.getDeclAttrs(this);
NewAttr->setNext(ExistingAttr);
ExistingAttr = NewAttr;
HasAttrs = true;
}
void Decl::invalidateAttrs(ASTContext &Context) {
if (!HasAttrs) return;
HasAttrs = false;
Context.eraseDeclAttrs(this);
}
const Attr *Decl::getAttrsImpl(ASTContext &Context) const {
assert(HasAttrs && "getAttrs() should verify this!");
return Context.getDeclAttrs(this);
}
void Decl::swapAttrs(ASTContext &Context, Decl *RHS) {
bool HasLHSAttr = this->HasAttrs;
bool HasRHSAttr = RHS->HasAttrs;
// Usually, neither decl has attrs, nothing to do.
if (!HasLHSAttr && !HasRHSAttr) return;
// If 'this' has no attrs, swap the other way.
if (!HasLHSAttr)
return RHS->swapAttrs(Context, this);
// Handle the case when both decls have attrs.
if (HasRHSAttr) {
std::swap(Context.getDeclAttrs(this), Context.getDeclAttrs(RHS));
return;
}
// Otherwise, LHS has an attr and RHS doesn't.
Context.getDeclAttrs(RHS) = Context.getDeclAttrs(this);
Context.eraseDeclAttrs(this);
this->HasAttrs = false;
RHS->HasAttrs = true;
}
void Decl::Destroy(ASTContext &C) {
// Free attributes for this decl.
if (HasAttrs) {
C.getDeclAttrs(this)->Destroy(C);
invalidateAttrs(C);
HasAttrs = false;
}
#if 0
// FIXME: Once ownership is fully understood, we can enable this code
if (DeclContext *DC = dyn_cast<DeclContext>(this))
DC->decls_begin()->Destroy(C);
// Observe the unrolled recursion. By setting N->NextDeclInContext = 0x0
// within the loop, only the Destroy method for the first Decl
// will deallocate all of the Decls in a chain.
Decl* N = getNextDeclInContext();
while (N) {
Decl* Tmp = N->getNextDeclInContext();
N->NextDeclInContext = 0;
N->Destroy(C);
N = Tmp;
}
this->~Decl();
C.Deallocate((void *)this);
#endif
}
Decl *Decl::castFromDeclContext (const DeclContext *D) {
Decl::Kind DK = D->getDeclKind();
switch(DK) {
#define DECL_CONTEXT(Name) \
case Decl::Name: \
return static_cast<Name##Decl*>(const_cast<DeclContext*>(D));
#define DECL_CONTEXT_BASE(Name)
#include "clang/AST/DeclNodes.def"
default:
#define DECL_CONTEXT_BASE(Name) \
if (DK >= Decl::Name##First && DK <= Decl::Name##Last) \
return static_cast<Name##Decl*>(const_cast<DeclContext*>(D));
#include "clang/AST/DeclNodes.def"
assert(false && "a decl that inherits DeclContext isn't handled");
return 0;
}
}
DeclContext *Decl::castToDeclContext(const Decl *D) {
Decl::Kind DK = D->getKind();
switch(DK) {
#define DECL_CONTEXT(Name) \
case Decl::Name: \
return static_cast<Name##Decl*>(const_cast<Decl*>(D));
#define DECL_CONTEXT_BASE(Name)
#include "clang/AST/DeclNodes.def"
default:
#define DECL_CONTEXT_BASE(Name) \
if (DK >= Decl::Name##First && DK <= Decl::Name##Last) \
return static_cast<Name##Decl*>(const_cast<Decl*>(D));
#include "clang/AST/DeclNodes.def"
assert(false && "a decl that inherits DeclContext isn't handled");
return 0;
}
}
CompoundStmt* Decl::getCompoundBody(ASTContext &Context) const {
return dyn_cast_or_null<CompoundStmt>(getBody(Context));
}
SourceLocation Decl::getBodyRBrace(ASTContext &Context) const {
Stmt *Body = getBody(Context);
if (!Body)
return SourceLocation();
if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Body))
return CS->getRBracLoc();
assert(isa<CXXTryStmt>(Body) &&
"Body can only be CompoundStmt or CXXTryStmt");
return cast<CXXTryStmt>(Body)->getSourceRange().getEnd();
}
#ifndef NDEBUG
void Decl::CheckAccessDeclContext() const {
assert((Access != AS_none || isa<TranslationUnitDecl>(this) ||
!isa<CXXRecordDecl>(getDeclContext())) &&
"Access specifier is AS_none inside a record decl");
}
#endif
//===----------------------------------------------------------------------===//
// DeclContext Implementation
//===----------------------------------------------------------------------===//
bool DeclContext::classof(const Decl *D) {
switch (D->getKind()) {
#define DECL_CONTEXT(Name) case Decl::Name:
#define DECL_CONTEXT_BASE(Name)
#include "clang/AST/DeclNodes.def"
return true;
default:
#define DECL_CONTEXT_BASE(Name) \
if (D->getKind() >= Decl::Name##First && \
D->getKind() <= Decl::Name##Last) \
return true;
#include "clang/AST/DeclNodes.def"
return false;
}
}
DeclContext::~DeclContext() {
delete static_cast<StoredDeclsMap*>(LookupPtr);
}
void DeclContext::DestroyDecls(ASTContext &C) {
for (decl_iterator D = decls_begin(C); D != decls_end(C); )
(*D++)->Destroy(C);
}
bool DeclContext::isDependentContext() const {
if (isFileContext())
return false;
if (isa<ClassTemplatePartialSpecializationDecl>(this))
return true;
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this))
if (Record->getDescribedClassTemplate())
return true;
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this))
if (Function->getDescribedFunctionTemplate())
return true;
return getParent() && getParent()->isDependentContext();
}
bool DeclContext::isTransparentContext() const {
if (DeclKind == Decl::Enum)
return true; // FIXME: Check for C++0x scoped enums
else if (DeclKind == Decl::LinkageSpec)
return true;
else if (DeclKind >= Decl::RecordFirst && DeclKind <= Decl::RecordLast)
return cast<RecordDecl>(this)->isAnonymousStructOrUnion();
else if (DeclKind == Decl::Namespace)
return false; // FIXME: Check for C++0x inline namespaces
return false;
}
DeclContext *DeclContext::getPrimaryContext() {
switch (DeclKind) {
case Decl::TranslationUnit:
case Decl::LinkageSpec:
case Decl::Block:
// There is only one DeclContext for these entities.
return this;
case Decl::Namespace:
// The original namespace is our primary context.
return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();
case Decl::ObjCMethod:
return this;
case Decl::ObjCInterface:
case Decl::ObjCProtocol:
case Decl::ObjCCategory:
// FIXME: Can Objective-C interfaces be forward-declared?
return this;
case Decl::ObjCImplementation:
case Decl::ObjCCategoryImpl:
return this;
default:
if (DeclKind >= Decl::TagFirst && DeclKind <= Decl::TagLast) {
// If this is a tag type that has a definition or is currently
// being defined, that definition is our primary context.
if (const TagType *TagT =cast<TagDecl>(this)->TypeForDecl->getAsTagType())
if (TagT->isBeingDefined() ||
(TagT->getDecl() && TagT->getDecl()->isDefinition()))
return TagT->getDecl();
return this;
}
assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
"Unknown DeclContext kind");
return this;
}
}
DeclContext *DeclContext::getNextContext() {
switch (DeclKind) {
case Decl::Namespace:
// Return the next namespace
return static_cast<NamespaceDecl*>(this)->getNextNamespace();
default:
return 0;
}
}
/// \brief Load the declarations within this lexical storage from an
/// external source.
void
DeclContext::LoadLexicalDeclsFromExternalStorage(ASTContext &Context) const {
ExternalASTSource *Source = Context.getExternalSource();
assert(hasExternalLexicalStorage() && Source && "No external storage?");
llvm::SmallVector<uint32_t, 64> Decls;
if (Source->ReadDeclsLexicallyInContext(const_cast<DeclContext *>(this),
Decls))
return;
// There is no longer any lexical storage in this context
ExternalLexicalStorage = false;
if (Decls.empty())
return;
// Resolve all of the declaration IDs into declarations, building up
// a chain of declarations via the Decl::NextDeclInContext field.
Decl *FirstNewDecl = 0;
Decl *PrevDecl = 0;
for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
Decl *D = Source->GetDecl(Decls[I]);
if (PrevDecl)
PrevDecl->NextDeclInContext = D;
else
FirstNewDecl = D;
PrevDecl = D;
}
// Splice the newly-read declarations into the beginning of the list
// of declarations.
PrevDecl->NextDeclInContext = FirstDecl;
FirstDecl = FirstNewDecl;
if (!LastDecl)
LastDecl = PrevDecl;
}
void
DeclContext::LoadVisibleDeclsFromExternalStorage(ASTContext &Context) const {
DeclContext *This = const_cast<DeclContext *>(this);
ExternalASTSource *Source = Context.getExternalSource();
assert(hasExternalVisibleStorage() && Source && "No external storage?");
llvm::SmallVector<VisibleDeclaration, 64> Decls;
if (Source->ReadDeclsVisibleInContext(This, Decls))
return;
// There is no longer any visible storage in this context
ExternalVisibleStorage = false;
// Load the declaration IDs for all of the names visible in this
// context.
assert(!LookupPtr && "Have a lookup map before de-serialization?");
StoredDeclsMap *Map = new StoredDeclsMap;
LookupPtr = Map;
for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
(*Map)[Decls[I].Name].setFromDeclIDs(Decls[I].Declarations);
}
}
DeclContext::decl_iterator DeclContext::decls_begin(ASTContext &Context) const {
if (hasExternalLexicalStorage())
LoadLexicalDeclsFromExternalStorage(Context);
// FIXME: Check whether we need to load some declarations from
// external storage.
return decl_iterator(FirstDecl);
}
DeclContext::decl_iterator DeclContext::decls_end(ASTContext &Context) const {
if (hasExternalLexicalStorage())
LoadLexicalDeclsFromExternalStorage(Context);
return decl_iterator();
}
bool DeclContext::decls_empty(ASTContext &Context) const {
if (hasExternalLexicalStorage())
LoadLexicalDeclsFromExternalStorage(Context);
return !FirstDecl;
}
void DeclContext::addDecl(ASTContext &Context, Decl *D) {
2009-02-20 08:56:18 +08:00
assert(D->getLexicalDeclContext() == this &&
"Decl inserted into wrong lexical context");
assert(!D->getNextDeclInContext() && D != LastDecl &&
"Decl already inserted into a DeclContext");
if (FirstDecl) {
LastDecl->NextDeclInContext = D;
LastDecl = D;
} else {
FirstDecl = LastDecl = D;
}
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
ND->getDeclContext()->makeDeclVisibleInContext(Context, ND);
}
/// buildLookup - Build the lookup data structure with all of the
/// declarations in DCtx (and any other contexts linked to it or
/// transparent contexts nested within it).
void DeclContext::buildLookup(ASTContext &Context, DeclContext *DCtx) {
for (; DCtx; DCtx = DCtx->getNextContext()) {
for (decl_iterator D = DCtx->decls_begin(Context),
DEnd = DCtx->decls_end(Context);
D != DEnd; ++D) {
// Insert this declaration into the lookup structure
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
makeDeclVisibleInContextImpl(Context, ND);
// If this declaration is itself a transparent declaration context,
// add its members (recursively).
if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
if (InnerCtx->isTransparentContext())
buildLookup(Context, InnerCtx->getPrimaryContext());
}
}
}
DeclContext::lookup_result
DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
DeclContext *PrimaryContext = getPrimaryContext();
if (PrimaryContext != this)
return PrimaryContext->lookup(Context, Name);
if (hasExternalVisibleStorage())
LoadVisibleDeclsFromExternalStorage(Context);
/// If there is no lookup data structure, build one now by walking
/// all of the linked DeclContexts (in declaration order!) and
/// inserting their values.
if (!LookupPtr) {
buildLookup(Context, this);
if (!LookupPtr)
return lookup_result(0, 0);
}
StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr);
StoredDeclsMap::iterator Pos = Map->find(Name);
if (Pos == Map->end())
return lookup_result(0, 0);
return Pos->second.getLookupResult(Context);
}
DeclContext::lookup_const_result
DeclContext::lookup(ASTContext &Context, DeclarationName Name) const {
return const_cast<DeclContext*>(this)->lookup(Context, Name);
}
DeclContext *DeclContext::getLookupContext() {
DeclContext *Ctx = this;
Unify the code for defining tags in C and C++, so that we always introduce a Scope for the body of a tag. This reduces the number of semantic differences between C and C++ structs and unions, and will help with other features (e.g., anonymous unions) in C. Some important points: - Fields are now in the "member" namespace (IDNS_Member), to keep them separate from tags and ordinary names in C. See the new test in Sema/member-reference.c for an example of why this matters. In C++, ordinary and member name lookup will find members in both the ordinary and member namespace, so the difference between IDNS_Member and IDNS_Ordinary is erased by Sema::LookupDecl (but only in C++!). - We always introduce a Scope and push a DeclContext when we're defining a tag, in both C and C++. Previously, we had different actions and different Scope/CurContext behavior for enums, C structs/unions, and C++ structs/unions/classes. Now, it's one pair of actions. (Yay!) There's still some fuzziness in the handling of struct/union/enum definitions within other struct/union/enum definitions in C. We'll need to do some more cleanup to eliminate some reliance on CurContext before we can solve this issue for real. What we want is for something like this: struct X { struct T { int x; } t; }; to introduce T into translation unit scope (placing it at the appropriate point in the IdentifierResolver chain, too), but it should still have struct X as its lexical declaration context. PushOnScopeChains isn't smart enough to do that yet, though, so there's a FIXME test in nested-redef.c llvm-svn: 61940
2009-01-09 04:45:30 +08:00
// Skip through transparent contexts.
while (Ctx->isTransparentContext())
Ctx = Ctx->getParent();
return Ctx;
}
DeclContext *DeclContext::getEnclosingNamespaceContext() {
DeclContext *Ctx = this;
// Skip through non-namespace, non-translation-unit contexts.
while (!Ctx->isFileContext() || Ctx->isTransparentContext())
Ctx = Ctx->getParent();
return Ctx->getPrimaryContext();
}
void DeclContext::makeDeclVisibleInContext(ASTContext &Context, NamedDecl *D) {
// FIXME: This feels like a hack. Should DeclarationName support
// template-ids, or is there a better way to keep specializations
// from being visible?
if (isa<ClassTemplateSpecializationDecl>(D))
return;
DeclContext *PrimaryContext = getPrimaryContext();
if (PrimaryContext != this) {
PrimaryContext->makeDeclVisibleInContext(Context, D);
return;
}
// If we already have a lookup data structure, perform the insertion
// into it. Otherwise, be lazy and don't build that structure until
// someone asks for it.
if (LookupPtr)
makeDeclVisibleInContextImpl(Context, D);
// If we are a transparent context, insert into our parent context,
// too. This operation is recursive.
if (isTransparentContext())
getParent()->makeDeclVisibleInContext(Context, D);
}
void DeclContext::makeDeclVisibleInContextImpl(ASTContext &Context,
NamedDecl *D) {
// Skip unnamed declarations.
if (!D->getDeclName())
return;
// FIXME: This feels like a hack. Should DeclarationName support
// template-ids, or is there a better way to keep specializations
// from being visible?
if (isa<ClassTemplateSpecializationDecl>(D))
return;
if (!LookupPtr)
LookupPtr = new StoredDeclsMap;
// Insert this declaration into the map.
StoredDeclsMap &Map = *static_cast<StoredDeclsMap*>(LookupPtr);
StoredDeclsList &DeclNameEntries = Map[D->getDeclName()];
if (DeclNameEntries.isNull()) {
DeclNameEntries.setOnlyValue(D);
return;
}
// If it is possible that this is a redeclaration, check to see if there is
// already a decl for which declarationReplaces returns true. If there is
// one, just replace it and return.
if (DeclNameEntries.HandleRedeclaration(Context, D))
return;
// Put this declaration into the appropriate slot.
DeclNameEntries.AddSubsequentDecl(D);
}
/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
/// this context.
DeclContext::udir_iterator_range
DeclContext::getUsingDirectives(ASTContext &Context) const {
lookup_const_result Result = lookup(Context, UsingDirectiveDecl::getName());
return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first),
reinterpret_cast<udir_iterator>(Result.second));
}
void StoredDeclsList::materializeDecls(ASTContext &Context) {
if (isNull())
return;
switch ((DataKind)(Data & 0x03)) {
case DK_Decl:
case DK_Decl_Vector:
break;
case DK_DeclID: {
// Resolve this declaration ID to an actual declaration by
// querying the external AST source.
unsigned DeclID = Data >> 2;
ExternalASTSource *Source = Context.getExternalSource();
assert(Source && "No external AST source available!");
Data = reinterpret_cast<uintptr_t>(Source->GetDecl(DeclID));
break;
}
case DK_ID_Vector: {
// We have a vector of declaration IDs. Resolve all of them to
// actual declarations.
VectorTy &Vector = *getAsVector();
ExternalASTSource *Source = Context.getExternalSource();
assert(Source && "No external AST source available!");
for (unsigned I = 0, N = Vector.size(); I != N; ++I)
Vector[I] = reinterpret_cast<uintptr_t>(Source->GetDecl(Vector[I]));
Data = (Data & ~0x03) | DK_Decl_Vector;
break;
}
}
}