Check类之duplicate declaration checking/Class name generation/Type Checking

本文深入探讨Java编译器中变量声明冲突检查、类名生成规则及类型检查机制。通过具体代码示例,解析checkTransparentVar、checkTransparentClass、checkUniqueClassName等方法如何确保代码的正确性和唯一性,以及checkType方法如何验证类型兼容性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

1、duplicate declaration checking

 

/** Check that variable does not hide variable with same name in
     *  immediately enclosing local scope.
     *
     *  e.g
     *  public void m1(boolean a){
     *       int a = 3;
     *       boolean a = true; // 不调用checkTransparentVar()方法,因为调用checkUnique()方法时能测出冲突
     *  }
     *
     *  @param pos           Position for error reporting.
     *  @param v             The symbol.
     *  @param s             The scope.
     */
    void checkTransparentVar(DiagnosticPosition pos, VarSymbol v, Scope s) {
        if (s.next != null) {
            for (Scope.Entry e = s.next.lookup(v.name);
                 e.scope != null && e.sym.owner == v.owner;
                 e = e.next()) {
                if (e.sym.kind == VAR &&
                    (e.sym.owner.kind & (VAR | MTH)) != 0 &&
                    v.name != names.error) {
                    duplicateError(pos, e.sym);
                    return;
                }
            }
        }
    }

e.g

	public void m1(boolean a){
		int a = 3;
		
		for(int x = 0;x<2;x++){
			int x = 3;
		}
	}

其中int a = 3与int x= 3将调用checkTransparentVar()方法检测出重复声明。

 

 

/** Check that a class or interface does not hide a class or
     *  interface with same name in immediately enclosing local scope.
     *  @param pos           Position for error reporting.
     *  @param c             The symbol.
     *  @param s             The scope.
     */
    void checkTransparentClass(DiagnosticPosition pos, ClassSymbol c, Scope s) {
        if (s.next != null) {
            for (Scope.Entry e = s.next.lookup(c.name);
                 e.scope != null && e.sym.owner == c.owner;
                 e = e.next()) {
                if (e.sym.kind == TYP && e.sym.type.tag != TYPEVAR &&
                    (e.sym.owner.kind & (VAR | MTH)) != 0 &&
                    c.name != names.error) {
                    duplicateError(pos, e.sym);
                    return;
                }
            }
        }
    }

 

e.g

	public void m1() {
		class A{}
		{
			class A{} // err Duplicate nested type A
		}
	

而对于e.sym.owner.kind为VAR的情况还没有举出例子。  

 

 /** Check that class does not have the same name as one of
     *  its enclosing classes, or as a class defined in its enclosing scope.
     *  return true if class is unique in its enclosing scope.
     *  @param pos           Position for error reporting.
     *  @param name          The class name.
     *  @param s             The enclosing scope.
     */
    boolean checkUniqueClassName(DiagnosticPosition pos, Name name, Scope s) {
        for (Scope.Entry e = s.lookup(name); e.scope == s; e = e.next()) {
            if (e.sym.kind == TYP && e.sym.name != names.error) {
                duplicateError(pos, e.sym);
                return false;
            }
        }
        for (Symbol sym = s.owner; sym != null; sym = sym.owner) {
            if (sym.kind == TYP && sym.name == name && sym.name != names.error) {
                duplicateError(pos, sym);
                return true;
            }
        }
        return true;
    }

e.g

	{
		class A {}
		interface A{} // A类型的冲突将由checkUniqueClassName()方法来检测 
	}
	{
		class B {
			class B {
			}
		}
	}

  

2、Class name generation

 

 

 /** Return name of local class.
     *  This is of the form    <enclClass> $ n <classname>
     *  where
     *    enclClass is the flat name of the enclosing class,
     *    classname is the simple name of the local class
     */
    Name localClassName(ClassSymbol c) {
        for (int i=1; ; i++) {
            Name flatname = names.
                fromString("" + c.owner.enclClass().flatname +
                           syntheticNameChar + i +
                           c.name);
            if (compiled.get(flatname) == null)
                return flatname;
        }
    }

 

 

e.g

package com.test07;
public class Test3{
	
	interface I {
	}

	// com.test07.Test3$1
	final I i1 = new I() {

	};
	
	// com.test07.Test3$2
	final I i2 = new I() {

	};

	{
		// com.test07.Test3$1B
		class B {
		}
	}


	public void m1() {
		// com.test07.Test3$2B
		class B {
		}
		// com.test07.Test3$1C
		class C {
		}
		// com.test07.Test3$3
		final I i3 = new I() {

		};
	}
	
	public void m2() {
		// com.test07.Test3$3B
		class B {
		}
		// com.test07.Test3$1D
		class D {
		}
	}

}

  

  

3、Type Checking

 

   /** Check that a given type is assignable to a given proto-type.
     *  If it is, return the type, otherwise return errType.
     *  @param pos        Position to be used for error reporting.
     *  @param found      The type that was found.
     *  @param req        The type that was required.
     */
    Type checkType(DiagnosticPosition pos, Type found, Type req) {
        // 不兼容的类型
        return checkType(pos, found, req, "incompatible.types");
    }

    Type checkType(DiagnosticPosition pos, Type found, Type req, String errKey) {
        if (req.tag == ERROR)
            return req;
        if (found.tag == FORALL)
            return instantiatePoly(pos, (ForAll)found, req, convertWarner(pos, found, req));
        if (req.tag == NONE)
            return found;
        if (types.isAssignable(found, req, convertWarner(pos, found, req)))
            return found;
        if (found.tag <= DOUBLE && req.tag <= DOUBLE)
            // 可能损失精度
            return typeError(pos, diags.fragment("possible.loss.of.precision"), found, req);
        if (found.isSuperBound()) {
            // 从 super-bound 类型{0}进行分配
            log.error(pos, "assignment.from.super-bound", found);
            return types.createErrorType(found);
        }
        if (req.isExtendsBound()) {
            log.error(pos, "assignment.to.extends-bound", req);
            return types.createErrorType(found);
        }
        return typeError(pos, diags.fragment(errKey), found, req);
    }

 

checkType方法主要是在Attr类中的check()方法调用的,这个方法的代码如下:

 /** Check kind and type of given tree against protokind and prototype.
     *  If check succeeds, store type in tree and return it.
     *  If check fails, store errType in tree and return it.
     *  No checks are performed if the prototype is a method type.
     *  It is not necessary in this case since we know that kind and type
     *  are correct.
     *
     *  @param tree     The tree whose kind and type is checked
     *  @param owntype  The computed type of the tree
     *  @param ownkind  The computed kind of the tree
     *  @param protokind    The expected kind (or: protokind) of the tree
     *  @param prototype       The expected type (or: prototype) of the tree
     */
    Type check(JCTree tree, Type owntype, int ownkind, int protokind, Type prototype) {
    	// prototype不允许为method type
        if (owntype.tag != ERROR && prototype.tag != METHOD && prototype.tag != FORALL) {
            if ((ownkind & ~protokind) == 0) {
                owntype = chk.checkType(tree.pos(), owntype, prototype, errKey);
            } else {
                log.error(tree.pos(), "unexpected.type",kindNames(protokind),kindName(ownkind));
                owntype = types.createErrorType(owntype);
            }
        }
        tree.type = owntype;
        return owntype;
    }

  

owntype与prototype都是Type类型,其tag取值是TypeTags类中的预先定义好的值。

ownkind与protokind都是int类型,其取值是Kinds预先定义好的值。

通过比较如上的两类型值,其实也就是比较了语法节点的Type类型与Symbol类型。

 

 

 

 

 /** Check that a type is within some bounds.
     *
     *  Used in TypeApply to verify that, e.g., X in V<X> is a valid type argument.
     *  @param pos           Position to be used for error reporting.
     *  @param a             The type that should be bounded by bs.
     *  @param bs            The bound.
     */
    private boolean checkExtends(Type a, Type bound) {
         if (a.isUnbound()) {
             return true;
         } else if (a.tag != WILDCARD) {
             a = types.upperBound(a);
             return types.isSubtype(a, bound);
         } else if (a.isExtendsBound()) {
             Type ut = types.upperBound(a);
             boolean result = types.isCastable(bound, ut , Warner.noWarnings);
             return result;
         } else if (a.isSuperBound()) {
             Type lt = types.lowerBound(a);
             boolean result = !types.notSoftSubtype(lt, bound);
             return result;
         }
         return true;
     }

e.g

class BC<T extends Closeable> {
	public void test() {
		BC<InputStream> a = null;
		BC<? extends InputStream> b = null;
		BC<? super InputStream> c = null;		
	}
}

当a.isExtendsBound()时调用了isCastable()方法。

当a.isSuperBound()时调用了notSoftSubtype()方法。

  

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

转载于:https://www.cnblogs.com/extjs4/p/7630654.html

<think>好的,我需要帮助用户解决SELinux中出现的“Duplicate declaration of type”错误。首先,我得理解这个错误的原因。根据用户提供的引用内容,SELinux的策略模块可能重复定义了某个型。这可能发生在用户自定义策略模块时,比如在编译.te文件生成.mod文件的过程中出现型重复声明。 接下来,我应该根据系统级指令来组织回答。用户需要结构清晰的中文回答,并且行内数学表达式要用$...$格式,不过这个问题可能不涉及数学公式。但需要注意正确引用提供的资料。用户还要求生成相关问题,并在引用处添加标识。 首先,检查错误的具体场景。用户在编译SELinux模块时使用了checkmodule命令,如引用[1]中的例子:[root@python log]# checkmodule -m -o local.mod local.te [^1]。这可能是在生成模块时遇到重复型定义的问题。 解决步骤可能包括: 1. 检查.te文件中的型定义,确认是否有重复的type声明。 2. 使用sesearch或seinfo工具查找已有型,避免重复。引用[2]提到的工具如seinfo和sesearch可以帮助查询现有策略[^2]。 3. 合并重复的型声明,或者重命名其中一个型。 4. 清理中间文件并重新编译模块。 生成的相关问题需要围绕SELinux策略编写、工具使用和常见错误处理,比如如何查询现有型,编译模块的步骤,或处理其他策略冲突。 需要确保回答符合用户要求的结构,分步骤说明解决方法,并正确引用提供的资料。同时,生成的问题要自然相关,帮助用户深入理解问题。</think>### SELinux中“Duplicate declaration of type”错误解决方法 当在SELinux策略文件中出现`Duplicate declaration of type`错误时,通常是因为在`.te`文件中重复定义了同一个型(type)。以下是逐步解决方案: --- #### **步骤1:定位重复的型声明** 1. 打开引发错误的策略文件(例如`local.te`),搜索重复的`type`声明。 ```bash grep "type " local.te | sort | uniq -d ``` 此命令会列出文件中重复定义的型名称。 --- #### **步骤2:检查系统中是否已存在该型** 使用SELinux工具`seinfo`查询现有策略中是否已声明该型: ```bash seinfo -t <型名> | grep <型名> ``` 如果输出结果中包含该型,说明系统中已存在同名定义,需避免重复声明[^2]。 --- #### **步骤3:合并或重命名型** - **合并声明**:若重复型是同一用途,删除多余的`type`行,保留一个定义。 - **重命名型**:若用途不同,修改型名称以避免冲突。例如: ```te type new_custom_type_t; # 原为custom_type_t ``` --- #### **步骤4:清理并重新编译模块** 1. 删除中间文件(如`.mod`和`.pp`): ```bash rm -f local.mod local.pp ``` 2. 重新编译策略模块: ```bash checkmodule -M -m -o local.mod local.te semodule_package -o local.pp -m local.mod semodule -i local.pp ``` --- #### **步骤5:验证策略加载** 检查新策略是否生效: ```bash semodule -l | grep local ``` 若列表中包含模块名,说明加载成功。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值